Вопрос по package, module, namespaces, python – Модули Python с одинаковыми именами (то есть повторное использование стандартных имен модулей в пакетах)

13

Предположим, у меня есть пакет, содержащий модули:

<code>SWS/
  __init.py__
  foo.py
  bar.py
  time.py
</code>

и модули должны ссылаться на функции, содержащиеся друг в друге. Кажется, у меня проблемы с моимtime.py модуль, так как есть стандартный модуль с таким же именем.

Например, в случае, если мойfoo.py Модуль требует как мойSWS.time и стандартный питонtime  модули, я столкнулся с проблемой, так как переводчик заглянет внутрь пакета и найдет мойtime.py модули, прежде чем он сталкивается со стандартомtime модуль.

Есть ли способ обойти это? Это ситуация «нет-нет» и следует ли повторно использовать имена модулей?

Любые решения и мнения о философии упаковки будут полезны здесь.

Посмотрите на httplib / httplib2 и urllib / urllib2. Это делает мир библиотек более уродливым, но это предпочтительнее именовать коллизии и неопределенное поведение. Silas Ray
Почему это очевидно? & Lt; / devilsadvocate & GT; MikeWyatt
Около 14 лет назад я сделал модуль под названием волна. Испытывая это после долгого времени, это больше не работало. Оказалось, что за это время был добавлен стандартный модуль с таким названием. Да, я знаю, я должен быть старым ... (и я не был ясновидящим). Довольно очевидно: не судите слишком быстро. Jacques de Hooge
Я думаю, совершенно очевидно, что вам не следует повторно использовать стандартные имена модулей Python. Это просто напрашивается на неприятности. Cryptite
Также стоит добавить, что питонstyle guide рекомендует использоватьclass_ надclass (конечное подчеркивание), когда вы пытаетесь избежать столкновения имен с ключевыми словами. Это может быть уместно здесь, и использоватьimport time_ as time. Darthfett

Ваш Ответ

4   ответа
8

какую версию Python вы используете. Если ваша целевая версия Python - 2.4 или старше (в 2015 году, я надеюсь, что нет), то да, это будет плохой практикой, поскольку нет способа (без хаков) разграничить два модуля.

Тем не менее, в Python 2.5+, я думаю, что повторное использование стандартных имен модулей libwithin a package namespace совершенно нормально; на самом деле этодух PEP328.

As Python's library expands, more and more existing package internal modules suddenly shadow standard library modules by accident. It's a particularly difficult problem inside packages because there's no way to specify which module is meant. To resolve the ambiguity, it is proposed that foo will always be a module or package reachable from sys.path . This is called an absolute import.

The python-dev community chose absolute imports as the default because they're the more common use case and because absolute imports can provide all the functionality of relative (intra-package) imports -- albeit at the cost of difficulty when renaming package pieces higher up in the hierarchy or when moving one package inside another.

Because this represents a change in semantics, absolute imports will be optional in Python 2.5 and 2.6 through the use of from __future__ import absolute_import

SWS.time ясноnot то же самое, что иtime и как читатель кода, я ожидал быSWS.time не только использоватьtime, но расширить это каким-то образом.

Так что еслиSWS.foo необходимо импортироватьSWS.timeтогда он должен использовать абсолютный путь:

# in SWS.foo

# I would suggest renaming *within*
# modules that use SWS.time so that
# readers of your code aren't confused
# with which time module you're using
from SWS import time as sws_time

Или следует использоватьexplicit относительный импорт, как в ответе Бакуриу:

# in SWS.foo

from . import time as sws_time

В том случае, если вам нужно импортировать стандартный libtime модуль в пределахSWS.time модуль, вам сначала нужно будет импортировать будущую функцию (только для Python 2.5+; Python 3+ делает это по умолчанию):

# inside of SWS.time
from __future__ import absolute_import

import time

time.sleep(28800)  # time for bed

Note: from __future__ import absolute_imports повлияет только на импортwithin модуль, в котором будущая функция импортируется и будетnot влияет на любой другой модуль (так как это будет вредно, если другой модуль зависит от относительного импорта).

@Bakuriu, черт побери. Я не знал, что ПКП могут измениться таким образом. Я обновлю свой ответ. Однако я по-прежнему буду придерживаться своего аргумента о том, что наличие упакованного модуля, имя которого совпадает с именем модуля stdlib верхнего уровня, не только допустимо, но и приветствуется.
Обратите внимание, что ваша цитата из PEP 8obsolete, Текущая версия PEP 8endorses using relative imports: quote: * явный относительный импорт является приемлемой альтернативой абсолютному импорту, особенно когда речь идет о сложных макетах пакетов, где использование абсолютного импорта было бы излишне многословным *
15

пакетов никогда не является хорошей идеей. Старайтесь избегать этого как можно больше. Однако в вашей ситуации есть обходные пути.

Поведение, которое вы видите, импортируя вашиSWS.time вместо stdlibtimeиз-за семантикиimport в древних версиях Python (2.x). Чтобы исправить это, добавьте:

from __future__ import absolute_import

в самом верху файла. Это изменит семантикуimport к тому из python3.x, что гораздо разумнее. В этом случае утверждение:

import time

Будет ссылаться только на модуль верхнего уровня. Так что переводчикnot рассмотреть вашSWS.time модуль при выполнении этого импорта внутри пакета, но он будет использовать только стандартную библиотеку.

Если модульinside Ваш пакет должен быть импортированSWS.time у вас есть выбор:

Using an explicit relative import:

from . import time

Using an absolute import:

import SWS.time as time

Так что вашиfoo.py будет что-то вроде:

from __future__ import absolute_import

import time

from . import time as SWS_time
Я бы сказал, что это неплохая идея.when the module name is in the presence of a namespaceкак пакет. Это дух PEP328. Смотрите мой ответ ниже.
5

При этом, если вы ищете потенциальные обходные пути или лучшее понимание проблемы, я предлагаю вам прочитать следующие вопросы SO:

Importing from builtin library when module with same name exists

How to access a standard-library module in Python when there is a local module with the same name?

0

действительно нет хорошего способа обойти это. Старайтесь не называть ваши модули как стандартные пакеты. Если вы действительно хотите позвонить в свой модульtimeЯ рекомендую использовать_time.py вместо. же если бы был способ сделать это, это сделало бы ваш код трудным для чтения и запутанным, когда дело дошло до двух временных модулей.

Похожие вопросы