我有一个本地目录名为“calendar”,其中包含一个“__init__.py”文件。
我想要“import calendar”导入标准库模块calendar,而不是由本地目录定义的模块。
我已经尝试过使用“from __future__ import absolute_import”和更改PYTHONPATH。
我不能只是重命名该目录,这真的有很好的理由。
我有一个本地目录名为“calendar”,其中包含一个“__init__.py”文件。
我想要“import calendar”导入标准库模块calendar,而不是由本地目录定义的模块。
我已经尝试过使用“from __future__ import absolute_import”和更改PYTHONPATH。
我不能只是重命名该目录,这真的有很好的理由。
''
或'.'
)始终位于sys.path
的顶部。sys.path
,而不是在回退到sys.path
之前查找相对导入。calendar
,要么(b)将其移动到其他包的子包中,而不是将其置于顶层。无论您有多好的理由,做正确的事情的理由可能更好。sys.path
:syspath = sys.path
sys.path = [path for path in sys.path if path.strip('.')]
import calendar
sys.path = syspath
无论你做什么,这都会引起巨大的问题。当你尝试导入本地包calendar
时——即使你是从完全不同的源文件导入——什么也不会发生,因为在sys.modules
中已经有一个名为calendar
的东西,所以那个源文件将只获得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
而且,根据你的模块运行顺序不同(可能很难预测,甚至不确定),在其他位置也有很大机会需要类似的hackery。
(如果您实际上从未需要导入本地包calendar
,那么您就不会遇到这个问题...但是我无法想象您可能有什么好理由...)
sys.path
通常包含系统范围内的站点包、发行版的分发包、每个用户的站点包、每个pip
安装包的目录、每个easy_install
安装包的eggfile等等。我看不出这会有什么帮助。如果这些名称仅供内部使用,则无法指定您想要的两者中的哪一个,那么拥有两者有什么用呢?如果它们是可访问的,那么您最终将不得不编写不同的代码,具体取决于bs4
是否安装为分发、sys-site、user-site等包... - abarnertpathlib
(来自标准库),它又会执行import os
(即非相对导入)。如果本地存在一个os.py
文件,那么就会使用该文件。如果你说不要使用这些名称,那没问题,但如果以后标准库中添加了新的模块呢? - calestyosys.path
,导入包后再将 sys.path
恢复为原始值。import sys
original_path = sys.path
sys.path = original_path[1:]
import calendar
sys.path = original_path
正如其他人所说,最好的选择是将日历模块重命名为一个标准库未使用的新模块。
但如果无法实现这一点,则可以创建另一个模块(在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
import sys
并自己重新排列sys.path
。但是,如果你说你实际上在sys.path
上有一个目录,其中有一个与内置模块/包同名的包/模块(即,你的calendar
在路径的顶层),你真的需要将其重命名(实际上还有更好的理由)。没有一般方法来解决顶级名称冲突。 - BrenBarn