在Python2.7中,如何使用主脚本中的变量和其他用户定义的函数



问题的一个小背景。我正在用Python2.7编写一个代码,它运行良好。但出于可用性和维护目的,我决定将其分解为模块,这对我来说是新的,因此遇到了一些问题。虽然我已经能够通过点击和试用的方法使它发挥作用,但不确定它是否是正确的方法,因此在这里分享它。这里共享的代码是对真实代码的简化复制,驱动相同的逻辑、顺序和方法。

MainEx.py是在最高级别上运行的脚本

from LogIn_1 import LogIn
global NumTry
NumTry = 2
LogIn()
# xx is here just to show NumTry variable is further used in MainEx script
xx = NumTry*3

基本上,我试图在这里交流的是NumTry变量在MainEx.py(最高级别的脚本)中使用,也在LogIn()函数中使用。并且也将被我正在创建的其他函数使用。

LogIn_1.py是一个用户定义的函数

def LogIn():
from MainEx import NumTry
# following are some computations involving NumTry
print NumTry

运行MainEx.py给出结果:

2
2

问题:1.不确定为什么生成两次结果2.MainEx导入LogIn_1,LogIn_1导入MainEx,这看起来很奇怪。一种乒乓球的情况,从彼此导入变量。

我能够通过以下改变来纠正结果:主要示例

from LogIn_1 import LogIn
global NumTry
NumTry = 2
#LogIn()
# xx is here just to show NumTry variable is further used in MainEx script
xx = NumTry*3

LogIn_1.py

def LogIn():
from MainEx import NumTry
# following are some computations involving NumTry
print NumTry
LogIn()

运行MainEx.py给出结果:

2

我正在努力了解最佳实践,以避免未来出现问题。

如果你在代码中添加了一堆打印语句,你可以遵循血腥的细节:

# MainEx.py
print 'MainEx: start'
from LogIn_1 import LogIn
print 'MainEx: after Login import'
global NumTry
NumTry = 2
print 'MainEx: before Login() call'
LogIn()
print 'MainEx: after Login() call'
xx = NumTry*3
print 'MainEx: finish'
# LogIn_1.py
print 'start LogIn_1'
def LogIn():
print '  Login(): start'
from MainEx import NumTry
print '  Login(): after MainEx import'
print NumTry
print '  Login(): finish'
print 'finish LogIn_1'

输出:

MainEx: start
start LogIn_1
finish LogIn_1
MainEx: after Login import
MainEx: before Login() call
Login(): start
MainEx: start                        # Code in MainEx running again!
MainEx: after Login import
MainEx: before Login() call
Login(): start
Login(): after MainEx import
2
Login(): finish
MainEx: after Login() call
MainEx: finish
Login(): after MainEx import
2
Login(): finish
MainEx: after Login() call
MainEx: finish

正如您所看到的,将(a)循环导入与(b)具有顶级副作用的代码相结合会导致不正常的结果。特别是,当from MainEx import NumTryLogin()调用中运行时,Python似乎必须重新执行MainEx中的代码,因为该模块还没有NumTry属性,导致双重打印。我真的没想到会有这样的结果。。。但它就在那里。

最佳实践建议:

  • 将导入语句放在模块的顶部,而不是函数或类内部。

  • 设计代码以避免循环导入。你的程序的模块最终有一种层次结构:你的低级别模块从你自己的代码库中什么都不导入;并且您的高级模块导入您的低级模块。

  • 设计您的模块,使其顶层不会发生。模块只应定义类、定义函数、分配常量或导入较低级别的模块。只有您的系统的主模块应该做一些事情——并且应该调用您的顶级函数(传入任何命令行参数),甚至该调用也应该是有条件的,如下所示:

    import sys
    def main(args):
    ...
    def foo():
    ...
    def bar():
    ...
    if __name__ == '__main__':
    main(sys.argv[1:])
    

相关内容

  • 没有找到相关文章

最新更新