我有一个我正在构建的Python程序,可以以两种方式之一运行:第一种是调用Python main.py,它会以友好的方式提示用户输入,然后通过程序运行用户输入。另一种方法是调用python batch.py -file-它将传递所有友好的输入收集,并通过程序一次性运行整个文件的输入值。

问题是,当我运行batch.py时,它从main.py中导入了一些变量/方法/等,当它运行以下代码时:

import main

在程序的第一行,它立即出错,因为它试图运行main.py中的代码。

如何阻止Python运行我正在导入的主模块中包含的代码?


不幸的是,你不知道。这是导入语法工作的一部分,它这样做很重要——记住def实际上是执行的东西,如果Python不执行导入,你就会,嗯,没有函数。

不过,由于您可能有权访问该文件,因此您可能能够查看导致错误的原因。可以通过修改环境来防止错误的发生。


使用if __name__ == '__main__'习惯用法——__name__是一个特殊变量,如果模块作为脚本运行,其值为'__main__',如果模块被导入,则为模块名。所以你会这样做

# imports
# class/function definitions
if __name__ == '__main__':
    # code here will only run when you invoke 'python main.py'

你可以这样写"main.py":

#!/usr/bin/env python

__all__=["somevar", "do_something"]

somevar=""

def do_something():
    pass #blahblah

if __name__=="__main__":
    do_something()

因为这就是Python的工作原理——class和def等关键字不是声明。相反,它们是实际执行的实时语句。如果它们没有被执行,您的模块将是空的。

惯用的方法是:

# stuff to run always here such as class/def
def main():
    pass

if __name__ == "__main__":
   # stuff only to run when not called via 'import' here
   main()

但是,它确实需要对导入的模块进行源代码控制。


由于Python的工作方式,当它导入模块时,有必要运行它们。

为了防止模块中的代码在导入时被执行,但只在直接运行时执行,你可以使用以下if来保护它:

if __name__ == "__main__":
    # this won't be run when imported

您可能希望将此代码放在main()方法中,以便可以直接执行文件,或者导入模块并调用main()。例如,假设这是在文件foo.py中。

def main():
    print "Hello World"

if __name__ == "__main__":
    main()

这个程序可以通过python foo.py运行,也可以通过另一个python脚本运行:

import foo

...

foo.main()

试着从main.py导入所需的函数?所以,

from main import SomeFunction

可能是你在batch.py中命名的函数与main.py中的函数相同,当你导入main.py时,程序运行main.py函数而不是batch.py函数;执行上述操作可以解决这个问题。我希望。


将代码放入函数中,直到调用该函数它才会运行。在main.py中应该有一个main函数。声明如下:

if __name__ == '__main__':
  main()

然后,如果调用python main.py, main()函数将运行。如果你导入main.py,它就不会。此外,为了清晰起见,您可能应该将main.py重命名为其他名称。


虽然你不能在不运行代码的情况下使用import;有一种非常快速的方法可以输入你的变量;通过使用numpy。Savez,它将变量作为numpy数组存储在.npz文件中。然后,您可以使用numpy.load加载变量。

在scipy文档中可以看到完整的描述

请注意,这只适用于变量和变量数组,而不适用于方法等。


有一个Python增强提案PEP 299,旨在用def __main__:取代if __name__ == '__main__':习语,但它被拒绝了。在使用if __name__ = '__main__':)时,这仍然是一个很好的阅读来了解应该记住什么。


我做了一个简单的测试:

# test.py

x = 1
print("1, has it been executed?")


def t1():
     print("hello")
     print("2, has it been executed?")


def t2():
     print("world")
     print("3, has it been executed?")


def main():
     print("Hello World")
     print("4, has it been executed?")


print("5, has it been executed?")
print(x)

# while True:
# t2()

if x == 1:
     print("6, has it been executed?")

# test2.py

import test

当执行或运行test2.py时,运行结果:

1, has it been executed?

5, has it been executed?

1

6, has it been executed?

结论:当导入的模块没有添加if __name__=="__main__":时,当前模块将运行,导入模块中不在函数中的代码将按顺序执行,而函数中未调用的代码将不执行。

此外:

def main():
    # Put all your code you need to execute directly when this script run directly.
    pass

if __name__ == '__main__':
    main() 
else:
    # Put functions you need to be executed only whenever imported

A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file. The only things a user needed to modify were the input files and parameters. Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code


Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),

在main.py:

import os

#set environment variable to 0 (False):
os.environ['run_code'] = '0'


def binary_module():
    #retrieve environment variable, convert to integer
    run_code_val = int(os.environ['run_code'] )
    
    if run_code_val  == 0:
        print('nope. not doing it.')
    if run_code_val == 1:
        print('executing code...')
        # [do something]

...在任何加载main.py的脚本中:

import os,main

main.binary_module() 

输出:不。不做。

# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()

输出:执行代码…

*注意:上面的代码假设main.py和任何导入它的脚本存在于同一个目录中。