如何导入标准库模块而不是本地目录?

Jon*_*son 10 python

我有一个名为"calendar"的本地目录,其中包含"__init__.py"文件.

我希望"导入日历"导入标准库模块日历,而不是我本地目录定义的模块.

我已经尝试过"从__future__ import absolute_import"并改变PYTHONPATH.

有很好的理由我不能只重命名目录.真.

aba*_*ert 13

问题是当前工作目录(作为''或者'.',取决于版本/平台)总是在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
Run Code Online (Sandbox Code Playgroud)

但是,无论你做什么,这都会造成巨大的问题.当您稍后尝试导入本地包calendar,如果你从一个完全不同的源文件,什么都不会发生这样做-甚至,因为有一些已命名calendarsys.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
Run Code Online (Sandbox Code Playgroud)

而且,根据模块运行的顺序(可能不容易预测,甚至是确定性的),您很可能在其他位置需要类似的hackery.

(如果你真的不需要导入你的本地包calendar怎么办?好吧,在那种情况下你没有这个问题......但是我无法想象你的好理由可能是什么......)

  • 我很失望没有明确的方式来说"从标准库导入",甚至只是修改PYTHONPATH来说"从我首先安装Python的地方导入".谢谢你的详细信息! (4认同)
  • @JonathanPaulson:有一个3.0的建议去除所有内置的顶级包并将所有东西都移到一个巨大的`std`包中(就像C++ 98将整个stdlib移动到`std ::`命名空间一样) ),这本来可以解决这个问题...但如果你无法想象人们不想要的所有原因,你可以搜索长参数线程...... (2认同)