首页 文章

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

提问于
浏览
8

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

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

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

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

3 回答

  • 0

    问题是,启动Python时,当前工作目录(作为 '''.' ,取决于版本/平台)始终位于 sys.path 的顶部 .

    使用绝对导入没有区别 - 这只是首先查看 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 -even如果're doing so from a completely different source file—nothing will happen, because there'已经在 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 怎么办?那么,在这种情况下,你不要想象你的好理由可能是什么......)

  • 3

    您可以修改sys.path,导入包,然后将 sys.path 恢复为其原始值 .

    import sys
    original_path = sys.path
    sys.path = original_path[1:]
    import calendar
    sys.path = original_path
    
  • 11

    正如其他人所说,最好的选择是将日历模块重命名为标准库未使用的新模块 .

    但作为一种解决方法,如果不可能,您可以在放置本地 calendar.py 文件的目录之外创建另一个模块(在syspath中可见) .

    所以如果你有这样的层次结构:

    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
    

相关问题