1

我编写了一个 Python 3 控制台应用程序,它的结构与下面的示例相同。我想知道我应该如何导入模块以实现所需功能部分中指定的行为。

/foo
  |-/foo
  |   |-__init__.py
  |   |-/bar
  |   |   |-__init__.py
  |   |   |-eggs.py
  |   |-ham.py
  |   |-spam.py
  |-setup.py

在哪里:

  1. spam模块有main功能
  2. 模块导入模块中的spamHam类ham
  3. 模块导入模块中的hamEgg 类eggs
  4. 两个__init__.py文件都是空的
  5. 导入的基本setup.py文件setuptools

所需的功能

  • 我希望能够将控制台应用程序上传到PyPi。然后它可以作为一个包下载pip,并在终端中执行。

    ~/>> foo
    
  • 我还希望能够将它作为 Python 脚本运行。

    ~/foo>> python3 foo/spam.py
    

我发现,我认为是一种 hacky 方法来实现这一点。

(hacky)解决方案

为了获得已安装的包和 Python 脚本功能,我添加了一个try: ... except: ...可行的方法,但它似乎不是正确的方法。

try:
    from module import Class # import will work for running as script
except:
    # relative import will work for running as a package installed with pip
    from .module import Class 

如果我只保留相对导入,并尝试将代码作为 Python 脚本运行,我会得到:

Traceback (most recent call last):
  File "foo/spam.py", line 6, in <module>
    from .ham import Ham
ModuleNotFoundError: No module named '__main__.ham'; '__main__' is not a package

如果我离开常规导入并运行控制台应用程序,则会发生类似情况:

 Traceback (most recent call last):
  File ".../foo/spam.py", line 6, in <module>
    from ham import Ham
ModuleNotFoundError: No module named 'ham'

文件

__init__.py文件为空

spam.py

"""spam module"""

try:
    from ham import Ham
except:
    from .ham import Ham

def main():
    pass

if __name__ == "__main__:
    main()

ham.py

"""ham module"""

try:
    from eggs import Egg
except:
    from .eggs import Egg

class Ham:
    pass

eggs.py

"""eggs module"""

class Egg:
    pass

setup.py

from setuptools import setup, find_packages

setup(
    name="foo",
    version="1.0.0",
    author="Pablo",
    description="Example",
    packages=find_packages(),
    entry_points={
        "console_scripts": ["foo=foo.spam:main"]
    },
)
4

0 回答 0