导入时是否有退出模块的命令,例如函数的 return

Is there a command to exit a module when imported, like return for a function

当您在 python 中导入模块时,模块代码为“运行”。有时在模块中有分支逻辑很有用,例如检查包版本或平台或其他。有没有办法在到达文件末尾之前退出整个模块执行,相当于函数中的早期 return?

如果模块 运行 作为脚本,您可以 exit() 但这会主动引发异常并终止整个过程。我只想说,你已经完成了,不要 运行 下面的任何代码。

基本上我可以改造这个

if not <condition>:
    MY_CONSTANT = 3.14
    class blah():
       ...

    def foo(x):
       ...

    # rest of module....

进入

if <condition>:
    return from module

MY_CONSTANT = 3.14
class blah():
   ...

def foo(x):
   ...

# rest of module....

主要是为了让我不必编写很多看起来很奇怪的额外缩进级别的代码。

有点蹩脚,但如果你有一个模块 mylib.py 看起来像这样:

import sys

print("mylib - before sys.exit")
sys.exit(0)
print("mylib - after sys.exit")

然后是导入它的另一个文件:

try:
    import mylib
except SystemExit:
    pass

print("Done")

输出:

mylib - before sys.exit
Done
>>> 

您可以创建自定义 Loader that special-cases e.g. ImportError (1) as a shortcut to stop module execution. This can be registered via a custom Finder at sys.meta_path

所以如果你有以下模块要导入:

# foo.py

x = 1
raise ImportError  # stop module execution here
y = 2

您可以使用以下 finder/loader 导入该模块。它将一直执行到到达 raise ImportError.

为止
import importlib


class Loader(importlib.machinery.SourceFileLoader):
    def exec_module(self, module):
        try:
            super().exec_module(module)
        except ImportError:  # the module chose to stop executing
            pass


class Finder(importlib.machinery.PathFinder):
    @classmethod
    def find_spec(cls, fullname, path=None, target=None):
        spec = super().find_spec(fullname, path, target)
        if spec is not None:
            spec.loader = Loader(spec.name, spec.origin)  # register the custom loader
        return spec


import sys

sys.meta_path.insert(2, Finder())  # from now on the custom finder will be queried for imports


import foo

print(foo.x)  # prints 1
print(foo.y)  # raises AttributeError

(1) 使用 ImportError 来指示快捷方式显然有其缺点,例如,如果您的模块试图导入其他不存在的东西,这不会被报告为错误,但是模块只是停止执行。所以最好改用一些自定义异常。我只是为了示例而使用 ImportError