如何在Python中临时修改sys.path?

时间:2013-06-20 10:16:01

标签: python python-import

在Python的一个测试脚本中,我多次使用此模式:

sys.path.insert(0, "somedir")
mod =  __import__(mymod)
sys.path.pop(0)

是否有更简洁的方法来临时修改搜索路径?

4 个答案:

答案 0 :(得分:17)

您可以使用简单的context manager

import sys

class add_path():
    def __init__(self, path):
        self.path = path

    def __enter__(self):
        sys.path.insert(0, self.path)

    def __exit__(self, exc_type, exc_value, traceback):
        try:
            sys.path.remove(self.path)
        except ValueError:
            pass

然后要导入模块,您可以这样做:

with add_path('/path/to/dir'):
    mod = __import__('mymodule')

with语句sys.path的正文退出时,将恢复到原始状态。如果您只使用该块中的模块,则可能还需要从sys.modules删除其引用:

del sys.modules['mymodule']

答案 1 :(得分:15)

将值添加到sys.path只会暂时修改它,即仅对该会话进行修改。

通过更改PYTHONPATH和默认安装目录来完成永久性修改。

所以,如果暂时你只是为了当前会话,那么你的方法是可以接受的,但如果pop没有隐藏任何预期会发现的重要模块,你可以删除somedir部分。在PYTHONPATH,当前目录或默认安装目录中。

http://docs.python.org/2/tutorial/modules.html#the-module-search-path

答案 2 :(得分:1)

如果您正在测试使用 pytest,那么它们有一个很棒的 fixture,除了其他特性之外,它可以处理这种确切的情况:

<块引用>

monkeypatch 固定装置可帮助您安全地设置/删除属性, 字典项或环境变量,或修改 sys.path 为 输入... 所有修改将在请求测试功能或 夹具已完成。 raise 参数确定是否是 KeyError 或者如果设置/删除的目标将引发 AttributeError 操作不存在

在描述syspath_prepend时:

<块引用>

使用monkeypatch.syspath_prepend 修改sys.path,这也将 调用 pkg_resources.fixup_namespace_packages 和 importlib.invalidate_caches().

示例使用:

def test_myfunc(monkeypatch):
  with monkeypatch.context() as m:
    m.syspath_prepend('my/module/path')
    mod =  __import__(mymod)
  # Out here, the context manager expires and syspath is reset

答案 3 :(得分:0)

这是Eugene Yarmash提供的contextmanager实现的替代实现(使用contextlibpathlib.Path兼容):

@contextlib.contextmanager
def add_sys_path(path: Union[str, os.PathLike]) -> Iterator[None]:
  """Temporary add given path to `sys.path`."""
  path = os.fspath(path)
  try:
    sys.path.insert(0, path)
    yield
  finally:
    sys.path.remove(path)


with add_sys_path('/path/to/dir'):
  mymodule = importlib.import_module('mymodule')