2014-01-02 3 views
3

У меня есть локальный каталог с именем «calendar» с файлом «__init__.py».Как импортировать стандартный библиотечный модуль вместо локального каталога?

Я хочу «импортировать календарь», чтобы импортировать календарь стандартного библиотечного модуля, а не модуль, определенный моим локальным каталогом.

Я уже пробовал «из __future__ import absolute_import» и менял PYTHONPATH.

Есть хорошие причины Я не могу просто переименовать каталог. В самом деле.

+0

Вы можете «импортировать sys' и переупорядочить' sys.path' самостоятельно. Однако, если вы говорите, что на самом деле у вас есть каталог на 'sys.path', который имеет пакет/модуль с именем так же, как встроенный (т. Е. Ваш« календарь »находится на верхнем уровне пути), вы действительно нужно переименовать его (на самом деле есть даже лучшие причины). Нет общего способа разрешения конфликтов имен верхнего уровня. – BrenBarn

+1

Возможный дубликат: http://stackoverflow.com/questions/6031584/python-importing-from-builtin-library-when-module-with-same-name-exists –

ответ

6

Проблема заключается в том, что текущий рабочий каталог (или как '' или '.', в зависимости от версии/платформы) всегда в верхней части sys.path при запуске Python.

Использование абсолютного импорта не имеет значения - это просто означает посмотреть в sys.path сначала, вместо того, чтобы искать относительный импорт, прежде чем вернуться на sys.path.

Правильное решение, очевидно, заключается в том, чтобы либо (a) переименовать calendar, либо (b) переместить его в подпакет другого пакета вместо того, чтобы иметь его на верхнем уровне. Независимо от ваших хороших причин, хорошие причины для правильной работы, вероятно, еще лучше.

Но если вам нужно обойти это, вы можете сделать несколько вещей. Проще всего временно munge sys.path:

syspath = sys.path 
sys.path = [path for path in sys.path if path.strip('.')] 
import calendar 
sys.path = syspath 

Однако, независимо от того, что вы делаете, это не будет вызывать огромные проблемы. Когда вы позже попытаетесь импортировать свой локальный пакет calendar - даже если вы делаете это из совершенно другого исходного файла - ничего не произойдет, потому что уже есть что-то с именем calendar в sys.modules, так что другой исходный файл просто получит модуль stdlib calendar вместо вашего пакета.

Так что вам также нужно будет переименовать один или другой на лету и удалить его с sys.modules. Может быть, это:

syspath = sys.path 
sys.path = [path for path in sys.path if path.strip('.')] 
calmod = sys.modules.get('calendar') 
del sys.modules['calendar'] 
calendar = __import__('calendar') 
sys.modules['calendar'] = calmod 
sys.path = syspath 

И, в зависимости от того, на котором ваши модули задавят (которые не могут быть легко предсказуемы, или даже детерминированный), есть хороший шанс, что вы будете нуждаться в подобную повозка, запряженная волами в другом месте.

(Что делать, если вы никогда не должны импортировать локальный пакет calendar? Ну, в таком случае у вас нет этой проблемы ... но тогда я не могу себе представить, что ваши веские причины могли бы быть ...)

+3

Я очень разочарован тем, что не существует явного способ сказать «импорт из стандартной библиотеки» или даже просто изменить PYTHONPATH, чтобы сказать «импорт из того места, где я впервые установил Python». Спасибо за детали! –

+1

@JonathanPaulson: Но у вас не может быть двух модулей с одним и тем же квалифицированным именем, и это глобально в рамках всей вашей программы, поэтому такая функция языка просто упростит случайный запуск этой двусмысленности. Если это не ясно из второй половины моего ответа, мое объяснение, вероятно, отстой, поэтому, пожалуйста, дайте мне знать, что вы не получаете, и я попробую еще раз. – abarnert

+0

Теперь я разочарован тем, что внутреннее полное имя для модуля не имеет префикса с элементом sys.path, из которого он пришел. –

3

Вы можете изменить sys.path, импортировать пакет, а затем восстановить sys.path до своего первоначального значения.

import sys 
original_path = sys.path 
sys.path = original_path[1:] 
import calendar 
sys.path = original_path 
0

Как говорит остальное, лучшим вариантом является переименование модуля календаря в новый модуль, не используемый стандартной библиотекой.

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

Так что если у вас есть иерархия, как это:

project/ 
    __init__.py 
    app1/ 
     __init__.py 
     calendar.py 
     module_in_which_i_want_to_use_python_std_calendar.py 

Вы можете создать новый модуль с именем std_calendar.py за пределами приложения (за пределами calendar.py помещается). В этом файле вы можете импортировать календарь (это будет стандартный календарь модуль)

from calendar import * 

И иерархия будет:

project/ 
    __init__.py 
    std_calendar.py 
    app1/ 
     __init__.py 
     calendar.py 
     module_in_which_i_want_to_use_python_std_calendar.py 

В module_in_which_i_want_to_use_python_std_calendar.py можно использовать стандартный календарь с:

from project import std_calendar as calendar 
Смежные вопросы