【问题标题】:Why is Python running my module when I import it, and how do I stop it?为什么在我导入模块时 Python 会运行我的模块,我该如何停止它?
【发布时间】:2011-06-29 16:11:12
【问题描述】:

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

问题是,当我运行“batch.py​​”时,它会从“main.py”导入一些变量/方法/等,当它运行这段代码时:

import main

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

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

【问题讨论】:

标签: python module python-import


【解决方案1】:

因为这正是 Python 的工作方式 - 诸如 classdef 之类的关键字不是声明。相反,它们是被执行的真实的语句。如果它们没有被执行,你的模块将会是空的。

惯用的做法是:

# 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()

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

【讨论】:

  • 只是为了确认一下,您的评论“仅在此处不通过'import'调用时才运行的东西”暗示了要在 main() 下编写的命令,对吗?还是没关系??
  • @Goldname if 语句中的代码在导入时不会运行,但 main 函数本身已定义并且即使通过导入也可以使用。该模块在运行时只会执行 main 函数,如果导入则不会执行它。这一切都取决于你想做什么。如果您不需要其他地方的 main 中的命令,请务必将它们写在 if 中。但在我看来,它看起来更整洁。
【解决方案2】:

由于 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()

【讨论】:

    【解决方案3】:

    使用 if __name__ == '__main__' 成语 -- __name__ 是一个特殊变量,如果模块作为脚本运行,则其值为 '__main__',如果模块被导入,则为模块名称。所以你会做类似的事情

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

    【讨论】:

      【解决方案4】:

      不幸的是,你没有。这是导入语法工作原理的一部分,这样做很重要——记住def 实际上是执行的东西,如果 Python 没有执行导入,那么你会在没有函数的情况下被卡住。

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

      【讨论】:

      • 注意:如果没有办法修改环境以防止错误,也许你应该使用不同的模块
      • 我只是想根据您的回答确定。我写吗?当我们导入时,解释器看到 def 并将函数体分配给函数的名称,但它不执行它。这是真的吗?
      • @GreenFalcon 是的。 def foo(): doSomthingWakciy() 不会中断,直到您调用 foo()
      【解决方案5】:

      将代码放入函数中,直到您调用该函数,它才会运行。您的main.py 中应该有一个主要功能。与声明:

      if __name__ == '__main__':
        main()
      

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

      【讨论】:

        【解决方案6】:

        你可以这样写你的“main.py”:

        #!/usr/bin/env python
        
        __all__=["somevar", "do_something"]
        
        somevar=""
        
        def do_something():
            pass #blahblah
        
        if __name__=="__main__":
            do_something()
        

        【讨论】:

          【解决方案7】:

          有一个 Python 增强提案 PEP 299 旨在将 if __name__ == '__main__': 成语替换为 def __main__:,但被拒绝了。了解使用if __name__ = '__main__': 时要记住的内容仍然是一本不错的读物。

          【讨论】:

            【解决方案8】:

            我做了一个简单的测试:

            #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
            

            【讨论】:

              【解决方案9】:

              可能发生的一个小错误(至少它发生在我身上),尤其是在分发执行完整分析的 python 脚本/函数时,是在函数 .py 文件的末尾直接调用函数。 用户唯一需要修改的是输入文件和参数。 在导入时这样做,您将立即运行该功能。为了获得正确的行为,您只需删除对函数的内部调用并将其保留给真正的调用文件/函数/代码部分

              【讨论】:

                【解决方案10】:

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

                查看完整描述in the scipy documentation

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

                【讨论】:

                  【解决方案11】:

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

                  from main import SomeFunction
                  

                  可能是您在batch.py​​ 中将一个函数命名为与main.py 中的函数相同,而当您导入main.py 时,程序运行的是main.py 函数而不是batch.py​​ 函数;做上述应该解决这个问题。我希望。

                  【讨论】:

                  • 至少在 Windows 上不会。
                  • import main 不会将 main 中的所有内容导入当前命名空间。它只在当前命名空间中添加一个main 符号,因此不会发生冲突。
                  猜你喜欢
                  • 2011-09-25
                  • 2011-12-17
                  • 1970-01-01
                  • 2018-04-16
                  • 2019-08-06
                  • 2020-06-02
                  • 2020-04-25
                  • 2021-11-23
                  • 2018-11-08
                  相关资源
                  最近更新 更多