为啥在我导入模块时 Python 会运行我的模块,如何停止它?
Posted
技术标签:
【中文标题】为啥在我导入模块时 Python 会运行我的模块,如何停止它?【英文标题】:Why is Python running my module when I import it, and how do I stop it?为什么在我导入模块时 Python 会运行我的模块,如何停止它? 【发布时间】:2011-09-25 07:29:02 【问题描述】:我正在构建一个 Python 程序,它可以通过以下两种方式运行:第一种是调用“python main.py”,它会以友好的方式提示用户输入,然后通过运行用户输入该程序。另一种方法是调用“python batch.py -file-”,它将传递所有友好的输入收集并通过程序一次性运行整个文件的输入。
问题是,当我运行“batch.py”时,它会从“main.py”导入一些变量/方法/等,当它运行这段代码时:
import main
在程序的第一行,它立即出错,因为它试图运行“main.py”中的代码。
如何阻止 Python 运行我正在导入的“主”模块中包含的代码?
【问题讨论】:
***.com/questions/419163/what-does-if-name-main-do 【参考方案1】:不幸的是,你没有。这是导入语法工作原理的一部分,这样做很重要——记住def
实际上是执行的东西,如果 Python 没有执行导入,那么你会在没有函数的情况下被卡住。
不过,由于您可能有权访问该文件,因此您可能能够查看并查看导致错误的原因。可能可以修改您的环境以防止错误发生。
【讨论】:
注意:如果没有办法修改环境以防止错误,也许你应该使用不同的模块 我只是想根据您的回答确定。我写吗?当我们导入时,解释器看到 def 并将函数体分配给函数的名称,但它不执行它。这是真的吗? @GreenFalcon 是的。def foo(): doSomthingWakciy()
不会中断,直到您调用 foo()
【参考方案2】:
使用if __name__ == '__main__'
成语——__name__
是一个特殊变量,如果模块作为脚本运行,则其值为'__main__'
,如果模块被导入,则为模块名称。所以你会做类似的事情
# imports
# class/function definitions
if __name__ == '__main__':
# code here will only run when you invoke 'python main.py'
【讨论】:
【参考方案3】:你可以这样写你的“main.py”:
#!/usr/bin/env python
__all__=["somevar", "do_something"]
somevar=""
def do_something():
pass #blahblah
if __name__=="__main__":
do_something()
【讨论】:
【参考方案4】:因为这正是 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()
见What is if __name__ == "__main__"
for?
但是,它确实需要对正在导入的模块进行源代码控制。
【讨论】:
只是为了确认一下,您的评论“仅在此处不通过'import'调用时才运行的东西”暗示了要在 main() 下编写的命令,对吗?还是没关系?? @Goldname if 语句中的代码在导入时不会运行,但 main 函数本身已定义并且即使通过导入也可以使用。该模块在运行时只会执行 main 函数,如果导入则不会执行它。这一切都取决于你想做什么。如果您不需要其他地方的 main 中的命令,请务必将它们写在 if 中。但在我看来,它看起来更整洁。【参考方案5】:由于 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()
【讨论】:
【参考方案6】:尝试只从 main.py 导入所需的函数?所以,
from main import SomeFunction
可能是您在batch.py 中将一个函数命名为与main.py 中的函数相同,而当您导入main.py 时,程序运行的是main.py 函数而不是batch.py 函数;做上述应该解决这个问题。我希望。
【讨论】:
至少在 Windows 上不会。import main
不会将 main 中的所有内容导入当前命名空间。它只在当前命名空间中添加一个main
符号,因此不会发生冲突。【参考方案7】:
将代码放入函数中,直到您调用该函数,它才会运行。您的main.py
中应该有一个主要功能。与声明:
if __name__ == '__main__':
main()
然后,如果您调用python main.py
,main()
函数将运行。如果你导入main.py
,它不会。此外,为了清楚起见,您可能应该将 main.py
重命名为其他名称。
【讨论】:
【参考方案8】:虽然你不能在不运行代码的情况下使用import
;输入变量的方法非常快捷;通过使用numpy.savez
,它将变量存储为 .npz 文件中的 numpy 数组。之后您可以使用numpy.load
加载变量。
查看完整描述in the scipy documentation
请注意,这仅适用于变量和变量数组,不适用于方法等。
【讨论】:
【参考方案9】:有一个 Python 增强提案 PEP 299 旨在将 if __name__ == '__main__':
成语替换为 def __main__:
,但被拒绝了。了解使用if __name__ = '__main__':
时要记住的内容仍然是一本不错的读物。
【讨论】:
【参考方案10】:我做了一个简单的测试:
#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
【讨论】:
以上是关于为啥在我导入模块时 Python 会运行我的模块,如何停止它?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 VS Code 无法在我的程序中导入 timeit 模块?
求大神告知为啥python导入自定义模块时失败,导入自带模块却可以。