这样导入位于任意文件夹的Python脚本正确吗?

10 投票
4 回答
4903 浏览
提问于 2025-04-16 00:33

这段内容来自StackOverflow上之前的一个回答,差不多有一年了(而且这个回答没有被采纳)。我刚开始学习Python,发现系统路径真让人头疼。我在不同的文件夹里写了一些函数,现在想在新项目中导入它们,但不想费劲。

这是那段代码:

def import_path(fullpath):
""" Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
"""
path, filename = os.path.split(fullpath)
filename, ext = os.path.splitext(filename)
sys.path.append(path)
module = __import__(filename)
reload(module) # Might be out of date
del sys.path[-1]
return module

来源链接是: 如何在Python中进行相对导入?

我想知道我是否可以使用这段代码,以及是否有一些不太明显的副作用,可能会对新手造成困扰。

我打算像这样使用它:

import_path(/home/pydev/path1/script1.py)

script1.func1()

等等

这样使用这个函数是否“安全”?

4 个回答

0

我会担心你的脚本名字可能和路径中更早出现的某个模块重名。为了消除这种担心,我建议你先把路径完全替换成一个新的列表,只包含那个模块所在的目录,然后在导入完成后再把原来的路径放回去。此外,你应该把这个过程放在一个锁里,这样多个线程在做同样的事情时就不会互相干扰。

1

如前所述,请考虑线程安全性,如果适用的话。我更喜欢接近于类似帖子中发布的解决方案。下面是主要的不同之处:使用插入来指定导入的优先级,使用try...finally正确恢复sys.path,以及设置全局命名空间。

# inspired by Alex Martelli's solution to
# http://stackoverflow.com/questions/1096216/override-namespace-in-python/1096247#1096247
def import_from_absolute_path(fullpath, global_name=None):
    """Dynamic script import using full path."""
    import os
    import sys

    script_dir, filename = os.path.split(fullpath)
    script, ext = os.path.splitext(filename)

    sys.path.insert(0, script_dir)
    try:
        module = __import__(script)
        if global_name is None:
            global_name = script
        globals()[global_name] = module
        sys.modules[global_name] = module
    finally:
        del sys.path[0]
8

“官方”的完全安全的方法是使用标准Python库中的imp模块。

你可以用imp.find_module来查找你指定的目录列表中的模块——它会返回一个包含三个部分的元组(file, pathname, description)。如果找不到模块,file的值会是None(不过它也可能会抛出ImportError错误,所以你应该用try/except来处理这个情况,同时检查if file is None:)。

如果搜索成功了,接下来要用imp.load_module来加载模块(记得用try/finally来确保文件能被关闭!),传入之前得到的三个参数,第一参数必须是你传给find_module的那个name——这样就能返回模块对象了(呼,终于搞定了;-)。

撰写回答