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 モジュールをスクリプトとして直接実行することはできません (理由はよくわかりません)。

EDIT : 理由は、オプションの仕様である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.pypython -m mainまたはと入力して、アプリケーションを実行できますpython -c "import cclogger.api_main; api_main.main()"

PS:完全なソースをリンクしてくれてありがとう。質問で提供されたスタブよりもずっと役に立ちます。

于 2013-09-19T07:40:51.450 に答える
0

相対インポートはpython -m、Python 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 に答える