Pythonのインポートは、標準ライブラリ(Python 2.4)によってオーバーライドされています。

私は、私が書いているPythonパッケージを持っていて、名前の衝突のために標準ライブラリがファイルの代わりにインポートされるという問題があります。

たとえば、次のようなファイル構造があります。

package/__ init __。py

# No data in this file

package/module.py

#!/usr/bin/env python
print 'Loading module.py'
import signal

package/signal.py

#!/usr/bin/env python
print 'Loading signal.py'

これを実行すると、次の結果が得られます。

$ ./module.py
Loading module.py

私は取得したい:

$ ./module.py
Loading module.py
Loading signal.py

実際の質問:

したがって、 module.py を実行すると、インポートシグナルがstdlibバージョンに移動します。 module.py を代わりにsignal.pyをインポートするように強制する方法はありますか?

タグに書かれているように、これはpython-2.4.3で動くことができる必要があります。これは古いバージョンですが、RHEL 5に含まれています。


いくつかの追加情報

もう少し詳しく知りたければ、明示的に以下の設定をしています:

[10:30pm][~/test] tree .
.
|-- package
|   |-- __init__.py
|   |-- module.py
|   `-- signal.py
`-- script

[10:30pm][~/test] cat script
#!/usr/bin/env python
from package import signal

[10:30pm][~/test] cat package/__init__.py

[10:30pm][~/test] cat package/module.py 
#!/usr/bin/env python
print "Loading module.py"
import signal

[10:30pm][~/test] cat package/signal.py 
#!/usr/bin/env python
print "Loading signal.py"

[10:30pm][~/test] python ./script
Loading signal.py

[10:32pm][~/test] python ./package/module.py 
Loading module.py

[10:32pm][~/test] python -m package.module
python: module package.module not found

Please note that when I ran ./package/module.py that the print statement in ./package/signal.py was not fired. This implies that the signal that was loaded is the one from the stdlib.

5
RHEL :)を使用しないでください。 ./ configure;作る; make install をクリックします。ブラウ
追加された 著者 Matt Joiner,
名前の衝突を避けるためにあなたのパッケージの名前を変更するのは間違っていますか?
追加された 著者 S.Lott,
@Felix Yan: -m はPython2.6 +でのみ正しく動作します。 docs.python.org/whatsnew/…
追加された 著者 jfs,
RHELには何も問題はありません。 PythonをアップグレードするとRHEL 5システムがゴミ箱になります。2.4システムでは/ usr/bin/pythonを指定する必要があります。そうしないとyumが機能しなくなります。より良い選択肢は、EPELからPython 2.6を入手することです。彼はPythonをアップグレードする必要はないので、どうして安定したOSから変更する必要がありますか?
追加された 著者 jordanm,
@SLott:この例では、標準ライブラリの何かと矛盾しますが、ユーザが卵をインストールした場合にもこれは起こりませんか?
追加された 著者 Bill Lynch,
@FelixYan:あなたはPython 2.4を実行していますか?
追加された 著者 Bill Lynch,
しかし、次のようになります: $ python2 -m package.module => モジュールの読み込みsignal.pyを読み込む
追加された 著者 Felix Yan,
私はPython 2.7を実行している申し訳ありません
追加された 著者 Felix Yan,

3 答え

この場合の問題は、組み込みの signal モジュールがインタプリタの起動プロセスの一部としてインポートされることです。したがって、 module.py のコードが実行されるまでに、<​​code> signal という名前で sys.modules /code>を組み込みモジュールをその値として使用します。 import ステートメントは、最初に sys.modules が表示されるため、組み込みモジュールを返してそこで停止します。独自のカスタム signal.py を探すことさえ気にしません。

私は3つのソリューションを考えることができます:

  1. Rename your module. This is the easiest solution. You don't have to worry about your module names clashing with installed packages (eggs), because normally the import statement will search directories in the order specified by sys.path, and the current working directory when you run the interpreter is first on that list. signal is sort of a special case because it gets imported automatically before your code runs, but there are a limited number of modules for which that is true, and those are the only ones you have to avoid name clashes with.
  2. You can del sys.modules['signal'] and replace the entry with your own custom signal module. Don't actually do this unless your module is truly meant to be a drop-in replacement for the built-in signal. If you do, then any code that runs import signal from that point on will get your version, not the built-in one, and that could wreak havoc on any internal code that needs the signal module to function.
  3. You can use the imp module to get access to the internals of the import function, or at least equivalent code, which will allow you to bypass the check of sys.modules.

    If you really do need to do this, here's a code sample you could use:

    import imp, sys
    
    f, path, desc = imp.find_module('signal', sys.path)
    if f:
        f.close()
        signal = imp.new_module('signal')
        execfile(path, signal.__dict__)
    else:
        raise ImportError('signal.py not found')
    # signal is your module
    

    This code snippet is roughly equivalent to import signal except that it does not insert the module found into sys.modules, and it does not look for builtin modules before searching the path.

6
追加された
それは本当に不自由です。ご説明ありがとうございます。
追加された 著者 Bill Lynch,

ファイル階層

.
|-- package
|   |-- __init__.py
|   |-- module.py
|   `-- signal.py
`-- script
`-- __init__.py

script.py

#!/usr/bin/env python
from package import module

package/module.py

#!/usr/bin/env python
print 'Loading module.py'
from package import signal

package/signal.py

#!/usr/bin/env python
print 'Loading signal.py'

出力:

$ ./script 
Loading module.py
Loading signal.py

編集

これをpython 2.4.3のmodule.pyに変更してテストしました。

1
追加された
Python 2.4で実行すると失敗します。 rel="nofollow noreferrer"> gist.github.com/1495454
追加された 著者 Bill Lynch,
私は要点を新しい出力で更新しました。私は./scriptが動くことに同意します。それはいつもそうだった。また、./package/signal.pyを実行できるようにしたいと思います。
追加された 著者 Bill Lynch,
@sharth - 申し訳ありません。ちょうど変更を加え、Python 2.4.3でそれをテストしました
追加された 著者 jdi,

プロジェクトディレクトリ( package ディレクトリの親ディレクトリ)から:

python -mpackage.state # Python 2.6+
python2.4 -c'from package.state import test; test()'
  • always use absolute imports in your modules i.e., import package.signal instead of import signal unless you know what you're doing
  • make sure that package's parent directory is in sys.path. unittest2, nose, pytest test runners might do it for you
  • avoid module names that conflict with stdlib modules. Many test runners, code analyzers are broken and add directories with a module being processed to sys.path
  • python package/stat.py adds package to sys.path (see http://bugs.python.org/issue13475). You don't want that in this case
0
追加された