如何将python文件作为脚本运行并可作为包导入?

时间:2018-03-02 21:15:28

标签: python python-3.x python-import

我仍然试图抓住python 3并且我遇到了一个问题,我可以将.py文件作为脚本运行或者将其作为模块导入,但不是两者都可以。

目录结构

test/
  __init__.py
  test.py
  subwayclock/
    __init__.py
    subwayclock.py
    build/
      gen/
        __init__.py
        gtfs_realtime_pb2.py
        nyct_subway_pb2.py
      __init__.py

在这种情况下,test.py看起来像这样并且工作(rawFEED()是subwayclock.subwayclock中的一个函数):

from subwayclock.subwayclock import *

print(rawFEED())

但是,我无法直接运行脚本,即

python subwayclock/subwayclock.py

因为它会出现以下错误:

Traceback (most recent call last):
  File "subwayclock.py", line 32, in <module>
    from .build.gen.gtfs_realtime_pb2 import FeedMessage
SystemError: Parent module '' not loaded, cannot perform relative import

但是,如果我在subwayclock / subwayclock.py中将import语句修改为state(即删除了前导'。'):

from subwayclock.subwayclock import FeedMessage

我可以直接通过命令行运行subwayclock.py脚本,完美地调用 main 函数。

但是,当我运行原始的test.py文件时,import语句不再有效,我收到以下错误:

  Traceback (most recent call last):
  File "test.py", line 1, in <module>
        from subwayclock.subwayclock import *
      File "/var/www/test/subwayclock/subwayclock.py", line 32, in <module>
        from build.gen.gtfs_realtime_pb2 import FeedMessage
    ImportError: No module named 'build'

我可以让这个脚本独立运行并可导入吗?

3 个答案:

答案 0 :(得分:0)

您可以使用-m开关和完全限定的包路径

从包中运行脚本
python -m subwayclock.subwayclock

答案 1 :(得分:0)

在这种情况下,您可以使用绝对导入而不是相对导入,但是根据模块之间的依赖关系,它可能会导致一些奇怪的行为,其中从技术上讲,对象和类被定义了两次(一次在__main__脚本中,一次在另一个模块导入模块时)

执行此操作的正确方法是使用setup.py脚本创建正确的python包,并使用console_scripts入口点功能将函数公开为命令行脚本。

你的项目应该像这样组织。

/subwayclock
    /subwayclock
        __init__.py
        subwayclock.py
        ...
    setup.py

您的setup.py看起来像这样

from setuptools import setup, find_packages

setup(name='subwayclock',
      version='0.1',
      packages=find_packages(),
      zip_safe=False,
      entry_points = {
          'console_scripts': ['subwayclock_script_name=subwayclock.subwayclock:rawFEED'],
      }
)

然后你只需安装包

$ python setup.py install

(您也可以使用develop模式,因此您仍然可以使用它)

$ python setup.py develop

您将能够运行该命令行脚本

$ subwayclock_script_name

答案 2 :(得分:0)

我会尽力描述你,它是如何运作的,也是为了帮助。


相对导入

首先,python有许多不同的方法可以导入一些。 其中一些是相对导入(from .package import somemodule)左点意味着我们要从当前包中导入somemodule。这意味着我们应该声明我们的包(当我们导入这个模块时,我们从导入它,它有一个名字等)。


< p>

绝对导入(可能还有其他名称)

此导入在简单脚本中几乎无处不在,您必须知道这一点。
示例:

from app import db

其中app是python模块(app.py文件),而db是其中的变量。如果您想了解更多信息,read the docs


解决方案

我真的不知道如何避免这种情况,但如果我是你,我会这样做:

if __name__ == '__main__':
    from mypackage.module import function
else:
    from .module import function

你也可以在简单的情况下运行python -m package.module.function,但这不是一个好主意 或者,您可以将包目录添加到PYTHONPATH变量。请参阅good answer几乎相同的问题。