5

我有一个包裹cclogger。该目录有一个__init__.py文件,其中包含一些用于加载配置的代码。当我尝试api_main.py使用以下命令运行该目录中的文件时...

python -m cclogger.api_main

我收到以下错误:-

config loaded
Instantiating DB with: cclogger/test123@localhost:x
Instantiated ParseCentral
Register parser called by : CitiIndia
Registered parser for email:  CitiAlert.India@citicorp.com
Instantiated SmsParseCentral
Register parser called by : Citi Bank
Registered sms parser for address:  lm-citibk
Register parser called by : HDFC Bank
Registered sms parser for address:  am-hdfcbk
Traceback (most recent call last):
  File "/Users/applegrew/Dropbox/Credit Expense/cclogger/cclogger/api_main.py", line 4, in <module>
    from .bottle import run, default_app, debug, get
ValueError: Attempted relative import in non-package

错误上方显示的消息来自同一包中的模块,这些模块由__init__.py.

api_main.py 中的代码是:-

import re
import os

from .bottle import run, default_app, debug, get
from .common_util import date_str_to_datetime, UTCOffset, date_filter

#app = Bottle()

default_app().router.add_filter('date', date_filter)

from . import api, dev

@get('/index')
def index():
    return "CCLogger API main live and kicking."

if dev:
    debug(True)
    run(reloader=True, port=9000)
else:
    os.chdir(os.path.dirname(__file__))
    application = default_app()

我有 python 2.7.1。

我究竟做错了什么?您可以在https://github.com/applegrew/cclogger/tree/master/cclogger查看完整代码

4

2 回答 2

7

您不能直接将 python 模块作为脚本运行(我真的不知道原因)。

编辑:原因在PEP338中解释,这是该"-m"选项的规范。

2.5b1 的发布显示了此 PEP 和 PEP 328 之间令人惊讶的(尽管回想起来很明显)交互 - 显式相对导入在主模块中不起作用。这是因为相对导入依赖于__name__确定当前模块在包层次结构中的位置。在主模块中,值__name__always __main__,因此显式相对导入总是会失败(因为它们仅适用于包内的模块)。

对于 2.5 版本,建议始终在任何打算用作主模块的模块中使用绝对导入

要测试您的应用程序,请将 api_main 封装在一个函数中并创建一个将运行主循环的顶级 main.py 文件:

cclogger/api_main.py:

import re
import os


from .bottle import run, default_app, debug, get
from .common_util import date_str_to_datetime, UTCOffset, date_filter

#app = Bottle()


def main():
    default_app().router.add_filter('date', date_filter)

    from . import api, dev

    @get('/index')
    def index():
        return "CCLogger API main live and kicking."

    if dev:
        debug(True)
        run(reloader=True, port=9000)
    else:
        os.chdir(os.path.dirname(__file__))
        application = default_app()

/main.py

from cclogger import api_main


if __name__ == '__main__':
    api_main.main()

您可以通过键入 或 来运行您的python main.py应用python -m main程序python -c "import cclogger.api_main; api_main.main()"

PS:感谢您链接完整的源代码,它总是比问题提供的存根更有帮助。

于 2013-09-19T07:40:51.450 回答
0

相对导入在使用python -mPython 2.6 之后执行的模块中运行良好。如http://www.python.org/dev/peps/pep-0366中所述,当以这种方式执行时,该__package__属性会自动设置在模块上,以便相对导入起作用。这里导致失败的部分是重新加载器,它显然无法设置__package__.

编辑:看一眼代码,我发现这是一个瓶子 API。我没有检查瓶子,但它可能与 Flask 的重新加载器存在相同的问题,后者通过信任sys.argv. 问题是处理代码python -m(在runpy模块中)修改sys.argv,删除“-m”并将模块名称转换为文件名(这非常令人沮丧,但我相信他们有充分的理由)。因此,重新加载器实际执行的内容没有“-m”,并且设置的位__package__从不触发,导致不支持相对导入。

于 2014-07-24T06:56:38.513 回答