从其他文件调用函数时,避免在Kivy中进行多次导入

时间:2018-04-09 18:13:28

标签: python-3.x kivy

我正在使用kivy和python3.6开发一个小应用程序(我还是初学者)。为了清楚起见,我计划将代码分成不同的文件,但是在特定情况下我遇到了问题。我已经做了最小的工作实例来说明。

我有以下文件:

  • main.py
  • main.kv
  • module.py
  • module.kv

这是一个最小的代码:

main.py:

from kivy.app import App
from kivy.uix.button import Button
from kivy.lang import Builder
import module

Builder.load_file('module.kv')

class MainApp(App):
    pass

def function():
    print('parent function')

if __name__ == '__main__':
    MainApp().run()

main.kv:

CallFunction

module.py:

from kivy.uix.button import Button

class CallFunction(Button):
    def call_function(self):
        from main import function
        function()

module.kv:

<CallFunction>:
    id : parent_button
    text: 'Call parent button'
    on_press: self.call_function()

所以问题是,当我运行此代码时,我会收到警告

  

文件/home/kivy/python_exp/test/module.kv加载了多倍,您可能会有不想要的行为。

什么有用

  • 如果我要调用的函数是主app类的一部分,则没有问题
  • 如果该功能是module.py的一部分,则没有问题
  • 如果该功能是另一个模块的一部分,则没有问题

什么不起作用 我无法调用 main.py 中的函数。如果我使用导入函数作为module.py的开头,kivy有一个奇怪的行为,并调用所有两次。在 call_function 中调用允许有一个合适的接口,但是我收到多次加载文件的警告。

有一些简单的解决方法,我很清楚这一点,所以更多的是好奇心和更好地了解kivy的进口是如何运作的。有没有办法让它发挥作用?

我想在应用启动时使用main.py来初始化不同的东西。特别是我想在main.py中创建另一个类(不是kivy类)的实例,并在单击界面上的按钮时调用此实例上的方法。

谢谢:)

2 个答案:

答案 0 :(得分:0)

当你从另一个python模块导入东西时,python虚拟机会执行这个模块。在 call_function 中,您可以从文件导入功能,以便每次按 CallFunction 模块。 kv 已加载。

要解决此问题,建议在主kv文件中包含其他kv文件。

您还可以将import语句从方法移动到模块文件的顶部。

答案 1 :(得分:0)

您的kv文件被加载两次,因为代码执行了两次。这是由于pythons模块系统如何工作,而kivy刚刚意识到加载kv两次可能不是你想要的。

通常python对象存在于命名空间中。因此,当模块foo中的函数查找变量时,将在模块的命名空间中搜索变量。这样,如果您定义两个变量foo.varbar.var(在模块foobar中),它们就不会相互冲突并相互混淆。

棘手的是你执行的python文件是特殊的:它不会创建模块命名空间而是创建__main__命名空间。因此,如果您导入正在执行__main__的文件,它将使用新对象创建一个全新的命名空间并执行模块代码。如果导入已在当前会话中导入的模块,则模块代码将再次 执行,但已创建的命名空间可用。您甚至不需要两个文件,请将以下内容放在test.py

print("hello!")
print(__name__)
import test

如果您现在执行python test.py,您会看到两个hello!,一个__main__和一个test

您可以在the documentation中找到有关命名空间以及变量查找在python中如何工作的更多信息。

此外,如果您的function实际上做了一些工作并且改变了生活在main.py中的对象,那么您可能想要重新考虑信息流。通常,最好将状态和函数绑定在一起,然后将对象传递给它们调用它们的位置,即在示例中为CallFunction