这个片段来自SO的早期答案。它大约一岁(答案未被接受)。我是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
它来自这里: How to do relative imports in Python?
我想要一些关于我是否可以使用它的反馈 - 如果有任何不良副作用对新手来说可能不明显。
我打算用它这样的东西:
import_path(/home/pydev/path1/script1.py)
script1.func1()
等
以我想要的方式使用该功能是否“安全”?
答案 0 :(得分:8)
“官方”和完全安全的方法是标准Python库的imp模块。
使用imp.find_module在精确指定的可接受目录列表中查找模块 - 它返回一个3元组(file, pathname, description)
- 如果不成功,file
实际上是{{1} (但它也可以提升None
,因此您应该使用ImportError
/ try
来检查except
。
如果搜索成功,请在第一个参数之后调用imp.load_module(在if file is None:
/ try
中确保关闭文件!)传递给finally
的{{1}} - 它返回模块对象(phew; - )。
答案 1 :(得分:1)
如上所述,如果合适,请考虑线程安全。我更喜欢更贴近类似帖子中发布的解决方案。主要区别如下:使用insert指定导入的优先级,使用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]
答案 2 :(得分:0)
它确实感觉有点像黑客,但目前,我想不出任何可能发生的意外副作用,至少不会只是你只是将它用于你自己的脚本。基本上它的作用是暂时将指定文件的父目录(在您的示例中为/home/pydev/path1/
)添加到Python在查找要导入的模块时检查的路径列表。
我现在能想到的唯一风险是在多线程环境中出现,其中两个或多个线程(或进程)同时运行此功能。如果线程A想要从路径dirA/A.py
导入模块A,并且线程B想要从路径dirB/B.py
导入模块B,那么你最终会同时使用dirA
和dirB
在sys.path
短时间内。如果B.py
中有一个名为dirA
的文件,则线程B可能会找到(dirA/B.py
)而不是它正在寻找的文件(dirB/B.py
),因此导入错误的模块。出于这个原因,我不会在生产代码或您要分发给其他人的代码中使用它(至少在没有警告他们这个hack就在这里的情况下!)。在这种情况下,您可以编写一个更复杂的函数,允许您指定要导入的文件,而不会弄乱标准的路径集。 (这就是mod_python所做的事情)
答案 3 :(得分:0)
我担心您的脚本名称可能与路径中较早显示的模块相对应。为了消除这种担心,我会用一个只包含该模块的目录的新列表完全替换该路径,然后在导入完成后将其放回。另外,你应该将它包装在某种锁中,以便尝试做同样事情的多个线程不会相互干扰。