我正在尝试解析python源文件的给定路径,将每个文件和DoStuff™导入到每个导入的模块中。
def ParsePath(path):
for root, dirs, files in os.walk(path):
for source in (s for s in files if s.endswith(".py")):
name = os.path.splitext(os.path.basename(source))[0]
m = imp.load_module(name, *imp.find_module(name, [root]))
DoStuff(m)
上述代码有效,但无法识别包ValueError: Attempted relative import in non-package
我的问题基本上是,我如何告诉imp.load_module
某个模块是否属于某个包?
答案 0 :(得分:3)
您不能直接告诉导入器协议方法load_module
所提供的模块是包的一部分。取自PEP 302 New Import Hooks
内置
__import__
功能 (称为PyImport_ImportModuleEx 在import.c)然后将检查模块是否正在执行 import是包的包或子模块。如果它确实是一个 (子模块的一个)包,它首先尝试做相关的导入 到包(子模块的父包)。例如,如果 一个名为“垃圾邮件”的软件包会“导入鸡蛋”,它会首先查找 一个 模块名为“spam.eggs”。如果失败,导入继续作为 绝对导入:它将寻找一个名为“eggs”的模块。带点 名称导入工作几乎相同:如果包“垃圾邮件” “import eggs.bacon”(和“spam.eggs”存在,本身就是一个 包),“spam.eggs.bacon”尝试。如果失败“eggs.bacon”是 试过。 (这里没有描述更多细微之处,但是 这些与进口商的实施者无关 协议)。在机制中更深入,虚线名称导入被拆分 它的组件。对于“import spam.ham”,首先是“导入垃圾邮件” 完成,只有当成功导入“ham”作为子模块导入时 “垃圾邮件”。
导入器协议在个人的此级别运行 进口。当进口商收到请求时 “spam.ham” 模块“垃圾邮件”已经导入。
然后,您必须模拟内置导入的功能,并在加载子模块之前加载父包。
答案 1 :(得分:2)
函数imp.find_module
总是采用没有点的普通模块名称,但imp.load_module
的文档说
name参数表示完整的模块名称(包括包名称,如果这是包的子模块)。
所以你可以试试这个:
def ParsePath(path):
for root, dirs, files in os.walk(path):
for source in (s for s in files if s.endswith(".py")):
name = os.path.splitext(os.path.basename(source))[0]
full_name = os.path.splitext(source)[0].replace(os.path.sep, '.')
m = imp.load_module(full_name, *imp.find_module(name, [root]))
DoStuff(m)
答案 2 :(得分:0)
我遇到了同样的问题。好消息是有一种方法可以做到这一点,但你必须使用 imp 和 importlib 的组合。这是一个说明性的例子:
import imp
import importlib
package_path = r"C:\path_to_package"
package_name = "module"
module_absolute_name = "module.sub_module"
module_relative_name = ".sub_module"
# Load the package first
package_info = imp.find_module(package_name, [package_path])
package_module = imp.load_module(package_name, *package_info)
# Try an absolute import
importlib.import_module(module_absolute_name, package_name)
# Try a relative import
importlib.import_module(module_relative_name, package_name)
这将允许使用相对模块路径导入 sub_module ,因为我们已经加载了父包,并且importlib正确加载了子模块以了解它被导入的内容相对于。
我相信这个解决方案只适用于我们这些陷入Python 2. *的人,但需要有人确认。