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

pla*_*etp 23 python python-import

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

sys.path.insert(0, "somedir")
mod =  __import__(mymod)
sys.path.pop(0)
Run Code Online (Sandbox Code Playgroud)

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

Eug*_*ash 22

您可以使用简单的上下文管理器:

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
Run Code Online (Sandbox Code Playgroud)

然后要导入模块,您可以执行以下操作:

with add_path('/path/to/dir'):
    mod = __import__('mymodule')
Run Code Online (Sandbox Code Playgroud)

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

del sys.modules['mymodule']
Run Code Online (Sandbox Code Playgroud)


Ash*_*ary 15

附加值sys.path仅暂时修改它,即仅针对该会话.

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

因此,如果暂时只考虑当前会话,那么您的方法是可以的,但pop如果somedir没有隐藏任何预期在PYTHONPATH当前目录或默认安装目录中找到的重要模块,则可以删除该部分.

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

  • 我在导入后删除目录,以免减慢搜索速度(可能有数百个路径) (2认同)

Con*_*tor 5

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

import os
import sys
import contextlib
from typing import Iterator, Union

@contextlib.contextmanager
def add_sys_path(path: Union[str, os.PathLike]) -> Iterator[None]:
    """Temporarily add the 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')
Run Code Online (Sandbox Code Playgroud)