6

これが、Python2 の複雑なインポート メカニズムを理解していない単純なケースであることを願っています。私は次の設定をしています:

$> ls -ltr pypackage1 
total 3
-rw-r--r-- 1 pelson pelson   0 Aug 17 19:20 io.py
-rw-r--r-- 1 pelson pelson   0 Aug 17 19:20 __init__.py
-rw-r--r-- 1 pelson pelson  57 Aug 17 19:22 code.py
$> cat pypackage1/code.py 
from __future__ import absolute_import

import zipfile

__init__.pyつまり、空のandio.pyと 2 行のcode.pyファイルを含むスタブ パッケージしかありません。

インポートできますpypackage1

$> python -c "import pypackage1.code"

しかし、code.pyファイルを実行できません:

$> python pypackage1/code.py
Traceback (most recent call last):
  File "pypackage1/code.py", line 3, in <module>
    import zipfile
  File "python2.7/zipfile.py", line 462, in <module>
    class ZipExtFile(io.BufferedIOBase):
AttributeError: 'module' object has no attribute 'BufferedIOBase'

明らかに問題は、zipfileモジュールが組み込みモジュールよりも相対的な io モジュールを選択することに関係していますが、私はそれを修正したioと思いました。from __future__ import absolute_import

助けてくれてありがとう、

4

3 に答える 3

8

それが正しい振る舞いです。エラーを修正したい場合は、パッケージ内から実行しないでください。

パッケージ内にあるスクリプトを実行すると、python はそのディレクトリをパッケージとして解釈しないため、作業ディレクトリがPYTHONPATH. そのため、ioモジュールによってインポートされたモジュールは、標準ライブラリ内のモジュールではなく、zipfileあなたのモジュールです。io

パッケージの外 (またはbin/scriptsフォルダー) に簡単なランチャー スクリプトを作成し、それを起動することをお勧めします。このスクリプトには、次のようなものを単純に含めることができます。

from pypackage1 import code

code.main()

これに代わる方法は、実行するファイルがモジュールの一部であることを Python インタープリターに伝えることです。-mこれは、コマンド ライン オプションを使用して行うことができます。あなたの場合、あなたはしなければならないでしょう:

python -m pypackage1.code

の引数は、ファイル名ではなくモジュール名-mにする必要があることに注意してください。

于 2012-08-17T21:28:40.387 に答える
2

1 つの解決策はfrom __future__ import absolute_importzipfile.pyモジュールを配置することです。モジュールは絶対インポートを使用していますが、 zipfileモジュールはそうではありません。

もう 1 つのオプションは、パッケージ ディレクトリから実行しないことです。おそらく、パッケージ ディレクトリ内からインタープリターを実行するべきではありません。

于 2012-08-17T20:47:14.800 に答える
1

ファイル構造:

test.py
mylib/__init__.py
mylib/__collections.py
mylib/collections.py
mylib/mymod.py

このソリューションにより、次のことが可能になります。

  • __builtin__.collections と mylib.collections の両方を呼び出す test.py
  • mymod.py を使用して、ライブラリの一部として実行する場合とスタンドアロンで実行する場合 (テスト コードなど) の両方で、上記を呼び出します

test.py で:

from collections import deque
from mylib.collections import mydict

mylib/__init__.py で:

from __future__ import absolute_import
from . import collections
from . import mymod

mylib/__collections.py で:

class MyDict (dict):
    pass

mylib/collections.py で:

from __collections import *

mylib/mymod.py で:

from __future__ import absolute_import
from collections import deque
try:
    # Module running as part of mylib
    from .collections import MyDict
except ValueError:
    # Module running independently
    from __collections import MyDict

上記は Python >=2.5 で動作します。Python 3 では、'from __future__ import absolute_import' という行は必要ありません。

于 2013-10-09T11:04:57.510 に答える