【问题标题】:Python : How to call a global function from a imported modulePython:如何从导入的模块调用全局函数
【发布时间】:2020-04-23 12:00:47
【问题描述】:

是否可以在 Python 3 中从导入的函数调用全局函数?

./folders/folder1/def.py

def do_test():
  print("++ def.do_test()")
  global_function_1()
  print("-- def.do_test()")

./main.py

import importlib

def global_function_1():
  print("doing function 1 thing...")

mod = importlib.import_module('folders.folder1.def')
mod.do_test()

我有这样的错误。

++ def.do_test()
Traceback (most recent call last):
  File "C:\src\python\class2\main.py", line 10, in <module>
    mod.do_test()
  File "C:\src\python\class2\folders\folder1\def.py", line 4, in do_test
    global_function_1()
NameError: name 'global_function_1' is not defined

显然,如果在同一个文件中定义相同的函数就可以正常工作。

def global_function_1():
  print("calling the global function 1")


def do_test():
  print("++ def.do_test()")
  global_function_1()
  print("-- def.do_test()")

do_test()

结果是

++ def.do_test()
calling the global function 1
-- def.do_test()

如果 Python 不允许这样做,那么最接近的选择是什么? 在我的真实项目中,全局函数具有对全局的访问次数 变量。如果可能的话,我想避免把所有的全局函数 和变量在一个单独的类中。

编辑:以上是突出我的问题的代码摘录。在我的真实项目中,

  1. 我有十几个全局函数。因此,不建议通过函数参数传递其指针。
  2. 我在多个文件夹中有十几个其他 def.py 文件。我需要根据各种情况在运行时获取 def.py 文件。因此,不推荐从 main.py 到 def.py 的静态引用。

【问题讨论】:

  • from main import global_function_1 添加到def.py 有什么问题吗?
  • 您的问题中的代码中没有类,那么这与您的问题标题中的“来自类”有什么关系?
  • @Rawing -- 感谢您的建议。我把我的结果放在下面的 SmeltQuake 的回答中,他给了我同样的建议。
  • @martineau --- 你是对的。我混淆了另一种类型的实现。我只是纠正了这个问题。谢谢!

标签: python namespaces


【解决方案1】:

我能够得到main.py以使用以下设置。

(请注意,我必须在foldersfolder1子目录中添加一个空的__init__.pyfiles 才能使导入工作。)

文件.\class2\folders\folder1\def.py

from main import global_function_1

def do_test():
    print("++ def.do_test()")
    global_function_1()
    print("-- def.do_test()")

文件.\class2\main.py

import importlib

def global_function_1():
    print("doing function 1 thing...")

if __name__ == '__main__':
    mod = importlib.import_module('folders.folder1.def')
    mod.do_test()

输出:

++ def.do_test()
doing function 1 thing...
-- def.do_test()

【讨论】:

  • 谢谢!是的,它也适用于我的环境。我发现 "if name == 'main':" 除了空的 init.py 文件外,还需要让它工作.
  • 是的,这是一个不寻常的情况,main.py 导入的东西会导入它——这就是为什么需要if __name__ == '__main__':。我很惊讶没有它就不会进入无限导入循环......
【解决方案2】:

您创建的称为模块。如果没有导入到使用它的文件中,则无法使用。在您的情况下,def.py需要导入main。

可以这样导入:

from moduleFilename import moduleFunctionname

你可以这样做

moduleFunctionname()

替代方案:

import moduleFilename
moduleFilename.moduleFunctionname()

编辑:似乎 Rawing 的评论更快......

【讨论】:

  • 我试过了,但是又失败了。文件“C:\src\python\class2\folders\folder1\def.py”,第 1 行,在 中 import main 文件“C:\src\python\class2\main.py”,第 8 行,在 mod.do_test() AttributeError: 'module' object has no attribute 'do_test'
  • 你能发布你更新的代码吗?您可能将其导入错误的文件或拼写错误,但我不确定。
  • 等等,我想我明白你的意思了。从您发布的 main.py 中删除第一行和最后两行代码,我认为 importlib 不适合您想要做的事情。然后在 def.py 中添加“import main”,并通过在 def.py 中键入“main.() 来访问您的函数。这是有关该主题的文档:docs.python.org/2/tutorial/modules.html
  • 感谢您的进一步评论。但我不知道除了 importlib 之外的其他选项来动态导入文件(换句话说,我在实际项目中根据输入更改要导入的文件)。所以,很遗憾,我需要继续使用 importlib。
【解决方案3】:

如果你想让folders.folder1.def 独立于反向导入的东西,因为它看起来像是一个库或插件之类的东西,你可以将它作为回调来获取:

图书馆:

def do_test(callback):
  print("++ def.do_test()")
  callback()
  print("-- def.do_test()")

主模块:

import importlib

def global_function_1():
  print("doing function 1 thing...")

mod = importlib.import_module('folders.folder1.def')
mod.do_test(global_function_1)

【讨论】:

  • 感谢您的意见。是的,这行得通。但是,当我在实际项目中拥有十几个全局函数时,这是不可扩展的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 2022-11-11
  • 2019-06-27
  • 2021-12-14
相关资源
最近更新 更多