检测包是否 运行 作为 __init__.py 中的程序

Detect whether package is being run as a program within __init__.py

我有一个带有 __init__.py 的 Python 包,它导入了一些要作为包 API.

公开的东西
# __init__.py

from .mymodule import MyClass
# ...

我还希望能够将该包用作命令行应用程序,如 python -m mypackage 中所示,因此我有一个用于该目的的 __main__.py 文件:

# __main__.py

if __name__ == '__main__':
    from .main import main
    main()

到目前为止一切顺利。问题是,当包 运行 作为这样的程序时,我希望能够在 导入任何子模块之前 做一些事情 - 即改变一些环境加载某些第三方依赖项之前的变量。

我不知道该怎么做,至少不是以合理的方式。理想情况下,我想做类似的事情:

# __init__.py

def thePackageIsRunningAsAnApplication():
    # ???

def prepareEnvironment():
    # ...

if thePackageIsRunningAsAnApplication():
    prepareEnvironment()

from .mymodule import MyClass
# ...

问题是我认为thePackageIsRunningAsAnApplication()无法实施。通常的 __name__ == '__main__' 在这里不起作用,因为主模块 运行 是 __main__.py,而不是 __init__.py。事实上,我更愿意在 __main__.py 中定义 运行 prepareEnvironment,但我不知道如何在 运行 加载内部模块之前将其设置为 运行 =15=].

可能(不确定,实际上)通过延迟加载我的模块的依赖项,或者以某种方式延迟内部模块加载或其他方式来解决它,但我宁愿避免做这样的事情就是为了这个。

编辑:仔细想想,延迟加载可能也行不通。在示例中,MyClass 是 class,不是子模块,所以我不能延迟加载它。此外,MyClass 恰好继承自我提到的第三方依赖项的 class,所以我什至无法在不加载它的情况下定义它。

不是 100% 确定你想做什么 pre-import 明智。

据我所知,导入前没有预处理器步骤。 在 python 以外的其他语言中,通常有编译器标志可以在导入完成之前读取,但我不知道 python 是否有这些标志。

我可能的解决方案 pre-import 明智的做法是在你的其他子模块之前导入一个单独的包(当然你需要某种开关才能不使用它 运行 当你 call/use 包通常的外部方式)。 在导入包时,整个包是 运行 (如果没有 name == 'main' 部分)可以是用于在导入其他模块之前做一些事情。 但是如果你的意思是当你的程序以不同的方式被调用时解决一些环境问题,我认为没有办法让 multi-importpath 分辨率没有歧义。 如果您的包在本地保存,则有相对导入路径,但我认为它们不能那样使用。 不过会是一些有趣的实验。

为 运行 将您的代码作为脚本添加一个单独的入口点可能是有意义的,而不是使用 __main__.py,如您所见,它只能是 运行 包的 __init__.py 完全加载后。

位于顶层的像 run_mypackage.py 这样的简单脚本可以包含环境变量调整代码,然后可以导入和 运行 之后的包。

def prepare_environment():
    ...

if __name__ == "__main__":
    prepare_environment()            # adjust the environment firstt

    from mypackage.main import main  # then load the package afterwards
    main()