加载路径中的每个.py文件imp.load U模块抱怨相对影响

2024-04-25 21:03:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图为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给定模块是包的一部分?在


Tags: 模块pathnamein路径sourceforos
3条回答

我也有同样的问题。好消息是有一种方法可以做到这一点,但是必须结合使用impimportlib。下面是一个示例:

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)

这将允许子模块使用相对模块路径导入,因为我们已经加载了父包,并且importlib已正确加载子模块,以了解它相对于什么被导入。在

我相信这个解决方案只对我们这些困在python2.*中的人是必要的,但是需要有人来证实这一点。在

不能直接告诉Importer Protocol方法load_module给定的模块是包的一部分。取自PEP 302 New Import Hooks

The built-in __import__ function (known as PyImport_ImportModuleEx in import.c) will then check to see whether the module doing the import is a package or a submodule of a package. If it is indeed a (submodule of a) package, it first tries to do the import relative to the package (the parent package for a submodule). For example if a package named "spam" does "import eggs", it will first look for a module named "spam.eggs". If that fails, the import continues as an absolute import: it will look for a module named "eggs". Dotted name imports work pretty much the same: if package "spam" does "import eggs.bacon" (and "spam.eggs" exists and is itself a package), "spam.eggs.bacon" is tried. If that fails "eggs.bacon" is tried. (There are more subtleties that are not described here, but these are not relevant for implementers of the Importer Protocol.)

Deeper down in the mechanism, a dotted name import is split up by its components. For "import spam.ham", first an "import spam" is done, and only when that succeeds is "ham" imported as a submodule of "spam".

The Importer Protocol operates at this level of individual imports. By the time an importer gets a request for "spam.ham", module "spam" has already been imported.

然后,必须模拟内置导入的功能,并在加载子模块之前加载父包。在

函数imp.find_module总是采用一个没有点的简单模块名,但是imp.load_module的文档说明

The name argument indicates the full module name (including the package name, if this is a submodule of a package).

所以你可以试试这个:

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)

相关问题 更多 >