【问题标题】:Python - 2 arguments instead of one?Python - 2 个参数而不是一个?
【发布时间】:2020-12-12 18:58:08
【问题描述】:

Python 代码:

class Importer:
    from importlib import __import__, reload
    from sys import modules

    libname = ""
    import_count = 0
    module = None

    def __init__(self, name):
        self.libname = name
        self.import_count = 0

    def importm(self):
        if self.libname not in self.modules:
            self.module = __import__(self.libname)
        else:
            print("must reload")
            self.module = self.reload(self.module)
        self.import_count += 1

# test out Importer

importer = Importer("module")

importer.importm() # prints Hello
importer.importm() # prints Hello
importer.importm() # prints Hello (again)
print(importer.import_count)

上面的Python(3.8.1)代码在OnlineGDB,如果运行会报错:

TypeError: reload() takes 1 positional argument but 2 were given

当我在 Python 中打开 importlib 库时,我看到了这个:


# ... (previous code; unnecessary)

_RELOADING = {}


def reload(module): ## this is where reload is defined (one argument)
    """Reload the module and return it.

    The module must have been successfully imported before.

    """
    if not module or not isinstance(module, types.ModuleType): ## check for type of module
        raise TypeError("reload() argument must be a module")
    try:
        name = module.__spec__.name
    except AttributeError:
        name = module.__name__

    if sys.modules.get(name) is not module: ## other code you (probably) don't have to care about
        msg = "module {} not in sys.modules"
        raise ImportError(msg.format(name), name=name)
    if name in _RELOADING:
        return _RELOADING[name]
    _RELOADING[name] = module
    try:
        parent_name = name.rpartition('.')[0]
        if parent_name:
            try:
                parent = sys.modules[parent_name]
            except KeyError:
                msg = "parent {!r} not in sys.modules"
                raise ImportError(msg.format(parent_name),
                                  name=parent_name) from None
            else:
                pkgpath = parent.__path__
        else:
            pkgpath = None
        target = module
        spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target)
        if spec is None:
            raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name)
        _bootstrap._exec(spec, module)
        # The module may have replaced itself in sys.modules!
        return sys.modules[name]
    finally:
        try:
            del _RELOADING[name]
        except KeyError:
            pass

# ... (After code; unnecessary)

所有双井号 (##) cmets 都是我的

很明显reload 有 1 个参数,它会检查该参数是否是一个模块。在the OGDB (OnineGDB) code 中,我只传递了一个参数(很确定),它是模块类型(很可能)。如果我删除该参数(您可以编辑 OGDB),它会给出:

TypeError: reload() argument must be module

因此,出于某种原因,Python 一直认为我的论点比实际的要多。我让它工作的唯一方法是编辑importlib 文件,让reload 有两个参数(不是一个好主意)。

我尝试运行 PDB,但没有帮助。

谁能发现任何明显错误的地方,比如实际上有两个参数?

【问题讨论】:

  • 请在问题中包含minimal reproducible example
  • 当您像self.reload 一样调用它时,它会隐式添加self 作为第一个参数。
  • self.reload 替换为reload。它首先起作用的原因是因为您在“类范围”内导入,我认为这是不好的做法。
  • 是的,我看到了。但是您应该在问题中添加代码。问题应该是独立的。
  • @LakshyaRaj 在课堂外进行导入。

标签: python python-3.x illegalargumentexception


【解决方案1】:

我需要做的是把imports 放在课堂之外让它工作。这里是the new OGDB。归功于@L3viathan。代码如下:

from importlib import __import__, reload
from sys import modules

class Importer:
    libname = ""
    import_count = 0
    module = None

    def __init__(self, name):
        self.libname = name
        self.import_count = 0

    def importm(self):
        if self.libname not in modules:
            self.module = __import__(self.libname)
        else:
            print("must reload")
            self.module = reload(self.module)
        self.import_count += 1

# test out Importer

importer = Importer("module")

importer.importm() # prints Hello
importer.importm() # prints Hello
importer.importm() # prints Hello (again)
print(importer.import_count)

【讨论】:

    【解决方案2】:

    您遇到问题是因为您正在调用self.reload(self.module),这实际上相当于调用reload(self, self.module)。要查看此内容,请尝试运行以下命令:

    class Example:
        def some_method(*args):
            print(args)
        def some_other_method(self):
            self.some_method(1)
    
    an_example = Example()
    example.some_other_method()
    

    您应该看到这会打印出 2 个参数,而不是 1 个(其中第一个是对 self 的引用)尽管我们只将一个参数传递给 some_method,并且 some_method 没有 self 参数.

    最好将reload 方法导入到您的importm 方法中(或完全在类之外!),如下所示:

        def importm(self):
            from importlib import __import__, reload
            if self.libname not in self.modules:
                self.module = __import__(self.libname)
            else:
                print("must reload")
                self.module = reload(self.module)
            self.import_count += 1
    

    【讨论】:

    • 我认为您实际上不需要导入重新加载...不过我可能是错的
    • @JoranBeasley : reloadimportlib 中的一个函数,所以我需要包含它
    • @user14749127:您的第一个示例不适用于我,因为reload 函数不在self 必须对其执行任何操作的类中。
    • 哦,你显然是对的......在python2中你不需要导入它......我猜在py3中改变了
    • @JoranBeasley 我相信它需要在 Python 3 中导入
    【解决方案3】:
    import mymodule
    
    reload(mymodule)
    

    它是如何工作的......我不确定你的问题是来自上面那一大堆文字,这通常用于将状态重置为其初始状态

    mymodule.py

    x = 5
    

    ma​​in.py

    from importlib import reload # in py2 you did not need to import it
    import mymodule
    print(mymodule.x) # 5
    mymodule.x = 8
    print(mymodule.x) # 8
    reload(mymodule)
    print(mymodule.x) # 5 again
    

    【讨论】:

    • 您可能没有注意到,但我的问题中的代码用于多次重新导入模块。在你的例子中只做一次就违背了它的目的。
    • 你可以在任何你想要的地方......你想要多少次......这只是向你展示如何使用重新加载
    • 哦,好的。这是有道理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-08
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    相关资源
    最近更新 更多