标签: python-importlib

在python 3.4中从imp转换为importlib时出现问题

我已经制作了一个可以加载插件的Python应用程序。这些插件是根据名称和路径加载的。

我目前正在使用

pluginModule = imp.load_source(pluginModuleName,  pluginModulePath)
Run Code Online (Sandbox Code Playgroud)

然后以这种方式在模块中获取类实例

# Load the module class and initialize it.
if hasattr(pluginModule, pluginClassName):
  try:
    pluginClassInst = getattr(pluginModule, pluginClassName)()
  except Exception as e:
    errorMsg = ('In plugin module [{}], {}'.format(os.path.basename(pluginModulePath), e))
    exceptionTracePrint(self._log)
    self._log.error(errorMsg)
    continue
Run Code Online (Sandbox Code Playgroud)

由于不建议使用imp lib,因此我想使用importlib。而获得类实例的唯一类似方法是使用

pluginModule = importlib.machinery.SourceFileLoader(pluginModuleName, pluginModulePath).load_module()
Run Code Online (Sandbox Code Playgroud)

这里很奇怪(我正在使用pyCharm作为IDE)。当我在调试模式下运行代码时,上面的命令可以正常工作,并且可以获取类实例。但是运行代码通常会给我以下错误。

pluginModule = importlib.machinery.SourceFileLoader(pluginModuleName, pluginModulePath).load_module()
AttributeError: 'module' object has no attribute 'machinery'
Run Code Online (Sandbox Code Playgroud)

为什么运行和调试之间会有区别。有没有一种做我想要的替代方法。

我也尝试过

pluginModuleTmp = importlib.util.spec_from_file_location(pluginModuleName, pluginModulePath)
Run Code Online (Sandbox Code Playgroud)

这也给了我正确的数据,但是我无法以这种方式加载模块,或者至少我不知道如何

问候安德斯

python pycharm python-3.x python-importlib

5
推荐指数
1
解决办法
899
查看次数

如何使用 importlib 加载带有自定义全局变量的 Python 模块?

我正在尝试用 Python 构建一个小型构建系统,为我的 C++ 项目生成 Ninja 文件。它的行为应该类似于CMake;也就是说,bldfile.py脚本定义规则和目标,并可选择通过调用 递归到一个或多个目录bld.subdir()。每个bldfile.py脚本都有一个对应的bld.File对象。当bldfile.py脚本执行时,bld全局应该被预定义为该文件的bld.File实例,但仅限于该模块的范围

此外,我想以某种方式利用 Python 的字节码缓存,但该.pyc文件应该存储在构建输出目录中,而不是存储在脚本__pycache__旁边的目录中bldfile.py

我知道我应该使用importlib(需要 Python 3.4+ 就可以),但我不知道如何:

  1. 使用自定义全局变量加载并执行模块文件。
  2. 重用字节码缓存基础设施。

任何帮助将不胜感激!

python python-module python-importlib

5
推荐指数
1
解决办法
1778
查看次数

酸洗使用 importlib.util 导入的对象

我在使用 Python 的泡菜时遇到了一个问题。我需要通过将它们的文件路径提供给 importlib.util 来加载一些 Python 模块,如下所示:

import importlib.util
spec = importlib.util.spec_from_file_location('custom', 'C:\path\to\.py\file.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
Run Code Online (Sandbox Code Playgroud)

我想从加载的模块中实例化一些对象并将它们序列化以供以后使用,但是当我尝试时:

pickle.dump(module.ObjectFromModule(), open('C:\object\location\obj.p', 'wb'))
Run Code Online (Sandbox Code Playgroud)

我明白了:_pickle.PicklingError: Can't pickle : import of module 'custom' failed

如果我尝试对通过 import 语句导入的对象进行酸洗,则不会发生这种情况。我怎样才能绕过这个?

python pickle python-importlib

5
推荐指数
2
解决办法
1603
查看次数

在python3中使用importlib进行动态导入时出错

我一直在尝试importlib与python3(3.6)一起使用。

目录结构

main.py

#Note: I will only modify line 4 that uses importlib
import importlib
if __name__ == '__main__':
    print("In main.py")
    hello = importlib.import_module('hello', package='./')
    print("Loaded hello.py")
    hello.hello()
Run Code Online (Sandbox Code Playgroud)

你好

def hello():
    print('Hello world')
Run Code Online (Sandbox Code Playgroud)

文件夹/hello.py

def hello():
    print('Hello world in folder')
Run Code Online (Sandbox Code Playgroud)

观察结果

如果我做

hello = importlib.import_module('hello', package='./') 要么

hello = importlib.import_module('hello')

它从根文件夹导入hello.py并进行打印hello world

如果我做

hello = importlib.import_module('folder.hello')

它从根文件夹导入folder / hello.py并打印hello world in folder

但是如果我这样做

hello = importlib.import_module('hello', package='folder') 要么

hello = …

import python-import dynamic-import python-3.x python-importlib

5
推荐指数
1
解决办法
3511
查看次数

如何在超时的情况下动态导入不安全的 Python 模块?

我需要动态加载几个可能不安全的模块以进行测试。

关于安全性,我的脚本由低访问权限的用户执行。

尽管如此,我仍然需要一种方法来优雅地使导入过程超时,因为我不能保证模块脚本会终止。例如,它可以包含对input或无限循环的调用。

我目前正在使用Thread.joina timeout,但这并不能完全解决问题,因为脚本在后台仍然存在并且无法杀死线程。

from threading import Thread
import importlib.util

class ReturnThread(Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self, *args, **kwargs):
        super().join(*args, **kwargs)
        return self._return

def loader(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module) # This may run into an infinite loop
    return module

module_loader = ReturnThread(loader, ('module_name', 'module/path'))
module_loader.start()
module = module_loader.join(timeout=0.1)

# The thread might …
Run Code Online (Sandbox Code Playgroud)

python import module python-3.x python-importlib

5
推荐指数
1
解决办法
676
查看次数

当也用作类型提示时如何处理额外的要求?

我想更新一个库,以便要求是可选的(使用extras_require)。

不幸的是,从可选需求导入的类在库中随处用作类型提示。这是一个例子:

from typing import List
try:
    from extra.sub import ExtraFoo, ExtraBar
except ImportError:
    pass

def optional(foo: ExtraFoo) -> List[ExtraBar]:
    pass

def greeting(name: str) -> str:
    return 'Hello ' + name

if __name__ == '__main__':
    greeting('John Smith')
Run Code Online (Sandbox Code Playgroud)

optional()在此示例中,如果extra未安装,我们将不会使用。事实上,这样的代码会引发一个NameErrorsinceExtraFooExtraBar用作类型提示。

一个可能的解决方法是在块中声明class ExtraFoo: passand 。然而,在同一模块中具有多种类型的代码中到处都存在这样的情况。class ExtraBar: passexcept

我想避免通过虚拟导入声明污染代码。有没有通用的方法来处理这种情况(例如代理模块)?

python setuptools python-import python-3.x python-importlib

5
推荐指数
1
解决办法
228
查看次数

打包Python资源(Manifest.in vs package_data vs data_files)

似乎非 python 资源包含在 python 分发包中的四种方式之一:

  1. Manifest.in 文件(我不确定这何时优于 package_data 或 data_files)
  2. package_data in setup.py(用于python 导入包中包含资源)
  3. data_files in setup.py(用于包含python 导入包之外的资源)
  4. 所谓的东西setuptools-scm(我相信它使用你的版本控制系统来查找资源而不是manifest.in或其他东西)
  • 其中哪些可以从 访问importlib.resources
    (据我了解,这importlib.resources是访问此类资源的首选方式。)如果其中任何一个无法通过 访问importlib.resources,那么人们如何能够/应该访问这些资源?

  • 网上其他人因使用查找资源路径的建议而受到责骂__file__,因为安装的 Wheel 发行版可能存储为 zip 文件,因此甚至不会有正确的资源路径。轮子什么时候被提取到站点包中以及什么时候它们保持拉链状态?

python resources setuptools python-importlib

5
推荐指数
1
解决办法
1194
查看次数

使用Python的LazyLoader导入类导入顶级模块

如果我懒惰import os的话,我可以使用以下方法:

os = lazy('os')
Run Code Online (Sandbox Code Playgroud)

它会延迟加载库,但如果我这样做:

path = lazy('os.path')

正在LazyLoader加载os模块,然后延迟加载path子模块。我怎样才能防止这种情况发生?

另外我不知道这是否受支持,但我想知道你是否可以这样做:

os = lazy('os')
Run Code Online (Sandbox Code Playgroud)

但是该方法是否以惰性方式返回?

from os.path import isdir
Run Code Online (Sandbox Code Playgroud)

python lazy-loading python-3.x python-importlib

5
推荐指数
0
解决办法
424
查看次数

模块“importlib”没有属性“util”

我在我的树莓派 pi3 上使用 Python 3.7,我收到一个错误,我的模块 importlib 没有 util,你能告诉我如何解决这个问题吗?

如果我做:

pi@raspberrypi:~ $ python3
>>> import importlib
>>> dir(importlib)
Run Code Online (Sandbox Code Playgroud)

我得到:

['_RELOADING', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__import__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_bootstrap', '_bootstrap_external', '_imp', '_r_long', '_w_long', 'find_loader', 'import_module', 'invalidate_caches', 'reload', 'sys', 'types', 'warnings']
Run Code Online (Sandbox Code Playgroud)

所以 :

>>> importlib.util
Run Code Online (Sandbox Code Playgroud)

返回:

回溯(最近一次调用最后一次):文件“”,第 1 行,在 AttributeError:模块“importlib”没有属性“util”

我尝试使用 Python 3.8 但得到了相同的结果 提前谢谢

python python-3.x raspberry-pi python-importlib

5
推荐指数
1
解决办法
5023
查看次数

如何使用importlib打开包中的文件?

我正在尝试将我正在处理的简单网络抓取应用程序的后端放入一个包中,但该应用程序依赖于从腌制的 python 对象加载,我无法使用 importlib 将其加载到文件中. 以前,当我将所有代码都放在一个文件中并依赖于 open() 时,一切正常,但现在我在导入包时出现错误。出现此错误后,我尝试使用 importlib 加载文件,但无法使其工作。

我正在按照来自类似问题的此答案中的步骤进行操作:How to read a (static) file from inside a Python package? .

我的包中的文件结构是:

mypackage\
        __init__.py
        parse.py
        search.py
        categories\
                categories.pickle
                generate_categories_if_corrupted.py
Run Code Online (Sandbox Code Playgroud)

init .py的内容:

from %mymodule% import search
Run Code Online (Sandbox Code Playgroud)

发生错误的代码:

import importlib.resources as resources
from pickle import load
from . import categories

try:
    with resources.open_binary(categories, "categories.pickle") as cat:
        CATS = load(cat)
except FileNotFoundError:
    raise FileNotFoundError("")
Run Code Online (Sandbox Code Playgroud)

错误:

Traceback (most recent call last):
  File "%mypackage%\parse.py", line 15, in <module>
    with resources.open_binary(categories, "categories.pickle") as cat: …
Run Code Online (Sandbox Code Playgroud)

python pickle python-importlib

4
推荐指数
1
解决办法
868
查看次数