Можно ли использовать два пакета Python с одинаковыми именами? - PullRequest
9 голосов
/ 21 февраля 2011

У меня вопрос по импорту.Вопрос может показаться немного надуманным, но его цель - изучить ограничения использования абсолютного импорта для всех импортов в пакете. PEP8 крайне препятствует относительному импорту (отредактируйте: и Google Python Guide говорит, что никогда не следует их использовать).имеют одинаковое имя и оба используют абсолютный импорт в соответствии с PEP8:

    /pkg1
        mod1.py (contains an absolute import: 'import pkg1.mod2')
        mod2.py
        ...

    /pkg1
        mod1.py (contains an absolute import: 'import pkg1.mod3')
        mod3.py
        ...

Также предположим, что вы работаете над проектом Python, в котором вы хотите использовать оба пакета.Это может произойти, скажем, если вы хотите использовать две версии одного и того же пакета в проекте.

Есть ли способ включить оба пакета в иерархию вашего проекта, чтобы вы могли свободно использовать модули из обоих пакетовна протяжении всего проекта?

Для решения допустимо использовать такие вещи, как использование псевдонимов импорта и временное изменение sys.path.Но нельзя менять содержимое любого из пакетов.

Ответы [ 4 ]

12 голосов
/ 21 февраля 2011

Короткий ответ - нет, Python не принимает два пакета с одинаковыми именами. (Существуют вещи, называемые «пакетами пространства имен», которые позволяют одному пакету быть реализованным в нескольких каталогах, но они требуют, чтобы соответствующие пакеты были настроены для взаимодействия друг с другом).

Способ, которым PEP 8 препятствует явному относительному импорту, является одним из его более сомнительных советов, именно потому, что он затрудняет переименование пакета, чтобы избежать конфликтов имен. Если два пакета используют относительный импорт, вы можете просто переименовать один из них или вложить его в другой пакет и покончить с этим.

псевдонимы импорта здесь вам не помогут, потому что именно имя, заканчивающееся на sys.modules, имеет значение и использует имя модуля в качестве импортированного, а не имя, которое в конечном итоге будет связано при импорте модуль.

Если вы хотите стать действительно экзотичным, вы можете написать свой собственный импортер (см. PEP 302 и 3.x importlib документация ). Если вы решите зайти так далеко, вы можете делать практически все, что захотите.

2 голосов
/ 21 февраля 2011

Мои первоначальные тесты (в Python 2.6 и 3.1) предполагают, что может работать следующее:

import sys, re

import foo as foo1
for k in sys.modules:
    if re.match(r'foo(\.|$)', k):
        newk = k.replace('foo', 'foo1', 1)
        sys.modules[newk] = sys.modules[k]
        # The following may or may not be a good idea
        #sys.modules[newk].__name__ = newk
        del sys.modules[k]

sys.path.insert(0, './python')
import foo as foo2
for k in sys.modules:
    if re.match(r'foo(\.|$)', k):
        newk = k.replace('foo', 'foo2', 1)
        sys.modules[newk] = sys.modules[k]
        # The following may or may not be a good idea
        #sys.modules[newk].__name__ = newk
        del sys.modules[k]

Тем не менее, я проверил это только на очень простых пакетах и ​​попробовал только как любопытство. Одна проблема, это, вероятно, ломается reload. Python не предназначен для работы с несколькими пакетами с одинаковым именем верхнего уровня.

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

0 голосов
/ 21 февраля 2011

На самом деле, вы должны использовать пространства имен (пакеты), чтобы правильно разделить, какие модули вы хотите использовать. В вашем коде выше.

/pkg1
 mod1 - can just import mod2
 mod2.py
 __init__.py

/pkg2
 mod1 - can just import mod2
 mod2.py
 __init__.py

А в остальных местах вы должны сделать import pkg1.mod1 или import pkg2.mod1 по желанию.

0 голосов
/ 21 февраля 2011

Почему вы хотите импортировать две разные версии пакетов? Я вижу, что это источник всех ваших проблем.

Я бы предложил переписать ваш код и использовать вместо него последний пакет.

...