这样导入位于任意文件夹的Python脚本正确吗?
这段内容来自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 个回答
我会担心你的脚本名字可能和路径中更早出现的某个模块重名。为了消除这种担心,我建议你先把路径完全替换成一个新的列表,只包含那个模块所在的目录,然后在导入完成后再把原来的路径放回去。此外,你应该把这个过程放在一个锁里,这样多个线程在做同样的事情时就不会互相干扰。
如前所述,请考虑线程安全性,如果适用的话。我更喜欢接近于类似帖子中发布的解决方案。下面是主要的不同之处:使用插入来指定导入的优先级,使用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]
“官方”的完全安全的方法是使用标准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
——这样就能返回模块对象了(呼,终于搞定了;-)。