2013-07-16 2 views
1

Я пытаюсь узнать больше о Python, просмотрев код в популярных библиотеках. Первая библиотека, которую я затронул, - python-requests от Kenneth Reitz.logging.NullHandler и __init__.py расположение файла в Python-запросах

То, что я сделал, это просто git clone <request_repo_url_from_github>, и теперь я проверяю код.

Я просмотрел файл __init__.py в requests/packages.

У меня есть несколько вопросов, чтобы спросить:

  1. Почему __init__.py внутри requests/packages, должен не быть __init__.py файл под requests напрямую? Или это просто, потому что это непосредственно клонированный и удаленный пакет от github, что так нравится?

  2. Второй вопрос относится к приведенному выше кодексу ниже. Что я хотел бы знать, так это то, что делает NullHandler? Я взглянул на документацию here, что значит иметь обработчик «no-op». Где этот обработчик будет использоваться библиотечными разработчиками? Я имею в виду, что особенного в этом?


import logging 
try: # Python 2.7+ 
    from logging import NullHandler 
except ImportError: 
    class NullHandler(logging.Handler): 
     def emit(self, record): 
      pass 
+0

Возможно, вас заинтересует ['logging_tree'] (http://rhodesmill.org/brandon/2012/logging_tree/), который отображает все регистраторы в виде древовидной диаграммы. –

ответ

1
  1. Имея __init__.py файл в каталоге, превращает этот каталог в пакет Python. Он не также включает подкаталоги в пакеты. Если вы посмотрите на дерево исходных кодов, вы увидите, что она выглядит следующим образом (с не соответствующими-файлы удалены)

    requests/ 
    | 
    |-- __init__.py 
    |-- packages/ 
        | 
        |-- __init__.py 
        |-- charade/ 
        | | 
        | |-- __init__.py 
        |-- urllib3/ 
         | 
         |-- __init__.py 
    

    Это определяет пакет верхнего уровня, requests, а также подпакеты requests.packages, requests.packages.charade и requests.packages.urllib3 , Определение этих пакетов необходимо, чтобы сделать их правильно импортируемыми.

    Чтобы ответить на интересующий вас вопрос, там is__init__.py файл под requests/ напрямую. Во всем дереве всего несколько.

  2. NullHandler ничего не делает. Он на месте, так что звонки в библиотеку logging можно использовать безоговорочно, даже если пользователь не настраивает регистраторов. В принципе, все регистраторы, прикрепленные к библиотеке регистрации, вызываются, когда urllib3 пытается зарегистрировать что-либо. Если есть нет подключенных регистраторов, тогда библиотека протоколирования выдает предупреждения. Это паршиво, так что это обходной путь, чтобы сделать код библиотеки проще, не заставляя людей регистрироваться.

+1

Спасибо, это потрясающе, когда 2-й самый большой вкладчик отвечает на ваш вопрос о библиотеке, в которой они вносят свой вклад. Большое спасибо, и диаграмма имеет большой смысл. Но, это отличается от того, как он выглядит, когда клонируется на рабочем столе. Кстати, его железо-окто-кошка дала вам подальше! : P –

+0

Рад помочь! Таким образом, диаграмма показывает базовую структуру в контроле, который у меня есть на моей рабочей машине, но с удалением всех файлов, отличных от '__init __. Py'. Как вы выглядите иначе? – Lukasa

3

Из того, что я помню requests, каталог packages содержит зеркала других зависимостей, которые автор решил связать вместе с requests вместо добавления в качестве зависимостей. Лично я бы просто сделал их зависимости, сославшись на конкретную версию, если это необходимо, но я уверен, что у них были причины для подхода к группировке.Я любом случае, она содержит __init__.py так что код может рассматривать его как модуль и сделать что-то вроде этого:

import requests.packages.urllib3 

Если вы посмотрите на requests directory on Github, вы увидите, что там действительно __init__.py в этом каталоге слишком. Если вы хотите иметь иерархию пакетов, вам нужен такой файл на каждом уровне, хотя в простейшем случае это может быть пустой файл.

Если вы не разместили __init__.py в каталоге, Python не узнает его как пакет - это предотвратит случайное включение модулей из мест, которые вы бы предпочли. Вы можете представить себе любое количество способов, с помощью которых каталог можно было бы назвать таким же, как пакет где-то еще, на sys.path и вызвать непонятную путаницу, но поскольку в нем не будет __init__.py, он будет игнорироваться Python.

Чтобы ответить на ваш второй вопрос, NullHandler предназначен для случаев, когда по какой-то причине удобно иметь обработчик регистрации, но на самом деле вы не хотите делать какие-либо записи. Вы можете использовать это, если используете библиотеку, которая выполняет ведение журнала, но в вашем случае вы фактически ничего не хотите регистрировать - вы устанавливаете NullHandler, чтобы выбросить эти сообщения регистрации, потому что это намного проще (и лучше), чем меняя свою библиотеку, чтобы вырезать код регистрации.

В этом примере я предположил, что вы можете добавить альтернативный журнал и просто установить уровень ведения журнала, чтобы на самом деле не создавались сообщения, но, возможно, проще просто использовать NullHandler.

+0

@Cartoo Спасибо за answe, я очень ценю это. –

+0

У нас была большая дискуссия о том, почему мы не просто включали их в качестве зависимостей в [этот закрытый вопрос] (https://github.com/kennethreitz/requests/issues/1384). – Lukasa

+0

Я полагаю, что библиотеки сложнее - для приложений вы можете просто сказать людям использовать virtualenv и сделать с ними. Было бы неплохо, если бы вы могли полагаться на другие библиотеки, чтобы поддерживать совместимость API, по крайней мере, в рамках основной версии, но я полагаю, что большинство людей не беспокоились об этом. Исходя из фона C++, я думаю, что я мог бы быть более привык к дисциплине, чем некоторые чистые программисты на Python. – Cartroo

Смежные вопросы