为使用“python -m zipapp”创建的独立应用程序导入模块的正确方法是什么?

Igo*_*ets 4 python python-import zipapp

我有一个模块,我将作为独立应用程序分发。该模块具有以下结构:

\n
$ tree -L 2 ./\n./\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mymodule\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __main__.py\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fun.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 mymodule.pyz\n
Run Code Online (Sandbox Code Playgroud)\n

mymodule/__main__.py包含下一行:

\n
#!/usr/bin/env python\n\nimport argparse\nimport sys\nimport os.path\nfrom mymodule.fun import Fun\n\ndef main():\n    sys.stdout.write(\'main is running\')\n    Fun().run()\n\nif __name__ == \'__main__\':\n    main()\n
Run Code Online (Sandbox Code Playgroud)\n

mymodule/fun.py包含下一行:

\n
#!/usr/bin/env python\n\nimport sys\n\nclass Fun:\n    """FUN"""\n\n    def __init__(self):\n        pass\n\n    def run(self):\n        sys.stdout.write("fun")\n
Run Code Online (Sandbox Code Playgroud)\n

如果我使用$ python -m mymodule输出运行模块\nmain is runningfun

\n

但是如果我使用它创建一个独立的应用程序$ python -m zipapp -p "/usr/bin/evn python" mymodule并运行它,$ python mymodule.pyz我会收到错误

\n
Traceback (most recent call last):\n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/runpy.py", line 193, in _run_module_as_main\n    "__main__", mod_spec)\n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/runpy.py", line 85, in _run_code\n    exec(code, run_globals)\n  File "mymodule.pyz/__main__.py", line 6, in <module>\nModuleNotFoundError: No module named \'mymodule\'\n
Run Code Online (Sandbox Code Playgroud)\n

出什么问题了import

\n

UPD:\nsys.path 输出

\n
Traceback (most recent call last):\n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/runpy.py", line 193, in _run_module_as_main\n    "__main__", mod_spec)\n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/runpy.py", line 85, in _run_code\n    exec(code, run_globals)\n  File "mymodule.pyz/__main__.py", line 6, in <module>\nModuleNotFoundError: No module named \'mymodule\'\n
Run Code Online (Sandbox Code Playgroud)\n

Igo*_*ets 5

首先,我使用错误的命令运行应用程序,正确的是:

\n
$ python mymodule\n
Run Code Online (Sandbox Code Playgroud)\n

要创建单文件应用程序并运行它,我需要使用:

\n
$ python -m zipapp -p "/usr/bin/evn python" mymodule\n$ python mymodule.pyz\n
Run Code Online (Sandbox Code Playgroud)\n

要运行单元测试,我需要使用:

\n
$ python -m unittest\n
Run Code Online (Sandbox Code Playgroud)\n

但单元测试由于错误而失败:

\n
======================================================================                                                          \nERROR: test_fun (unittest.loader._FailedTest)                                                                                   \n----------------------------------------------------------------------                                                          \nImportError: Failed to import test module: test_fun                                                                             \nTraceback (most recent call last):                                                                                              \n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/unittest/loader.py", line 153, in loadTestsFromName                    \n    module = __import__(module_name)                                                                                            \n  File "/Users/igork/developer/github/python/testzipapp/tests/test_fun.py", line 2, in <module>                                 \n    from mymodule.fun import Fun                                                                                                \n  File "/Users/igork/developer/github/python/testzipapp/mymodule/fun.py", line 8, in <module>                                   \n    from bar import Bar                                                                                                         \nModuleNotFoundError: No module named \'bar\'                                                                                      \n                                                                                                                                \n                                                                                                                                \n----------------------------------------------------------------------                                                          \nRan 1 test in 0.000s                                                                                                            \n                                                                                                                                \nFAILED (errors=1)                                                                                                               \n
Run Code Online (Sandbox Code Playgroud)\n

为了修复该错误,我在文件中添加了下一行tests/__init__.py

\n
======================================================================                                                          \nERROR: test_fun (unittest.loader._FailedTest)                                                                                   \n----------------------------------------------------------------------                                                          \nImportError: Failed to import test module: test_fun                                                                             \nTraceback (most recent call last):                                                                                              \n  File "/Users/igork/.pyenv/versions/3.6.4/lib/python3.6/unittest/loader.py", line 153, in loadTestsFromName                    \n    module = __import__(module_name)                                                                                            \n  File "/Users/igork/developer/github/python/testzipapp/tests/test_fun.py", line 2, in <module>                                 \n    from mymodule.fun import Fun                                                                                                \n  File "/Users/igork/developer/github/python/testzipapp/mymodule/fun.py", line 8, in <module>                                   \n    from bar import Bar                                                                                                         \nModuleNotFoundError: No module named \'bar\'                                                                                      \n                                                                                                                                \n                                                                                                                                \n----------------------------------------------------------------------                                                          \nRan 1 test in 0.000s                                                                                                            \n                                                                                                                                \nFAILED (errors=1)                                                                                                               \n
Run Code Online (Sandbox Code Playgroud)\n

总结一下:\n我使用的项目的结构是:

\n
testzipapp $ tree -L 2             \n.                                             \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 create-pyz.sh                              \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mymodule                                  \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __main__.py                            \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 bar.py                                \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fun.py                                \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mymodule.pyz                              \n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tests                                     \n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py                           \n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 test_fun.py                           \n   \n
Run Code Online (Sandbox Code Playgroud)\n

文件tests/test_fun.py是:

\n
import sys                    \nsys.path.append(\'mymodule\')   \n
Run Code Online (Sandbox Code Playgroud)\n

文件mymodule/__main__.py 是:

\n
testzipapp $ tree -L 2             \n.                                             \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 create-pyz.sh                              \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mymodule                                  \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __main__.py                            \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 bar.py                                \n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fun.py                                \n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 mymodule.pyz                              \n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tests                                     \n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py                           \n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 test_fun.py                           \n   \n
Run Code Online (Sandbox Code Playgroud)\n