モジュール__file__属性は絶対ですか、それとも相対ですか?


107

理解できません__file__。私が理解したこと__file__から、モジュールのロード元の絶対パスを返します。

これを生成するのに問題があります。returnsから実行されるabc.pywith oneステートメントがあります。返品から実行中。理由は何ですか?print __file__/d/projects/ python abc.pyabc.py/d/projects/abc.py


10
これがGuidoのコメント
kindall

回答:


98

ドキュメントから:

__file__モジュールがファイルからロードされた場合、モジュールのロード元のファイルのパス名です。この__file__属性は、インタープリターに静的にリンクされているCモジュールには存在しません。共有ライブラリから動的にロードされる拡張モジュールの場合、これは共有ライブラリファイルのパス名です。

質問へのコメントで@kindallによってリンクされたメーリングリストのスレッドから:

私はこの特定の例を再現しようとしませんでしたが、その理由は、すべてのインポートでgetpwd()を呼び出す必要がないことや、現在のディレクトリをキャッシュするためのある種のインプロセス変数を必要としないことです。(getpwd()は比較的低速で、完全に失敗することがあります。キャッシュしようとすると、間違いが発生する危険があります。)

代わりに、sys.pathの要素をウォークスルーして絶対パスに変換するsite.pyのコードを実行します。ただし、このコードは ''がsys.pathの前に挿入される前に実行されるため、sys.pathの初期値は ''です。

これ以降sys.pathは、含めないことを検討してください''

そのためsys.path、モジュールが含まれている部分の外側にいる場合は、絶対パスを取得しますsys.pathモジュールが含まれている部分の中にいる場合は、相対パスを取得します

現在のディレクトリにモジュールをロードし、現在のディレクトリsys.path、あなたは絶対パスを取得します。

現在のディレクトリにモジュールをロードし、現在のディレクトリsys.pathある場合は、相対パスが取得されます。


それは、モジュールへの「」からのパスがある場合、相対パスがない絶対パスのsys.pathの残りのために使用される場合、使用絶対あるであろうことを意味しない..
ゴー

4
あなたが現在のディレクトリにモジュールをロードし、現在のディレクトリがいる場合ではないsys.path、あなたは絶対パスを取得します。現在のディレクトリにモジュールをロードし、現在のディレクトリsys.pathある場合は、相対パスが取得されます。
agf '19

このため、sys.pathは含まれていません''
agf '19

取得しましたが、@ agf、/ homeからpython /foo/abc.pyを使用する場合、モジュールを含むsys.pathの部分は/ home / fooであり、現在のディレクトリは/ home /であると考えます。ファイルは私に相対パスを与えますか?
goh

55

__file__相対パスを使用してスクリプトを直接実行する場合を除いて、Python 3.4以降は絶対です

モジュールの__file__属性(および関連する値)には、デフォルトで常に絶対パスが含まれるようになりました。ただし__main__.__file__、相対パスを使用してスクリプトが直接実行された場合は例外です。(bpo-18416でBrett Cannonによって寄贈されました。)

ただし、シンボリックリンクが解決されるかどうかは不明です。

相対パスを渡す例:

$ python script.py

1
ありがとう。これは追跡するのが難しい事実です!
meawoppl 2014年

4
これはPython 3.4.0(Python 3.4.0 (default, Apr 11 2014, 13:05:11) [GCC 4.8.2] on linux)には当てはまりません。そして、私の裁判ではシンボリックリンクは解決されません。
Frozen Flame

@ FrozenFlame、3.4.1で修正されない場合は遠慮なくbugs.python.orgに報告してください
anatly techtonik 2015年

2
os.path.realpath(__file__)シンボリックリンクを解決する正しい方法はありますか?
kevinarpe 2015年


16

後半の簡単な例:

from os import path, getcwd, chdir

def print_my_path():
    print('cwd:     {}'.format(getcwd()))
    print('__file__:{}'.format(__file__))
    print('abspath: {}'.format(path.abspath(__file__)))

print_my_path()

chdir('..')

print_my_path()

Python-2。*では、2番目の呼び出しpath.abspath(__file__)は現在のディレクトリに基づいてを誤って決定します。

cwd:     C:\codes\py
__file__:cwd_mayhem.py
abspath: C:\codes\py\cwd_mayhem.py
cwd:     C:\codes
__file__:cwd_mayhem.py
abspath: C:\codes\cwd_mayhem.py

@techtonikで述べられているように、Python 3.4以降で__file__は絶対パスを返すため、これは正常に動作します。


...を除い__main__モジュール、__file__ できる相対パスです。
0xC0000022L

5

@kindallによって提供されるGuidoメールの助けを借りて、標準のインポートプロセスをの各メンバーでモジュールを見つけようとするものとして理解し、sys.pathこのルックアップの結果としてファイルすることができます(詳細はPyMOTWモジュールとインポートを参照してください)。したがって、モジュールがsys.path結果の絶対パスに配置されている場合は絶対ですが、相対パスに配置されている場合sys.path、結果のいる場合は相対です。

今、site.pyスタートアップファイルはにのみ、絶対パスを提供するの面倒をsys.path初期を除いて、''ので、あなたは(そのパス接頭辞の前に、絶対的にも作られていますPYTHONPATHを設定するよりも、他の手段でそれを変更しない場合sys.path)、あなたは常に絶対を取得しますパスが、モジュールが現在のディレクトリを介してアクセスされる場合。

面白い方法でsys.pathをだますと、何でも取得できます。

例として、コードを含むサンプルモジュールfoo.pyがある/tmp/とします。

import sys
print(sys.path)
print (__file__)

/ tmpに移動すると、次のようになります。

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
./foo.py

にいるとき、/home/userあなたを追加/tmpするとPYTHONPATH次のようになります:

>>> import foo
['', '/tmp', '/usr/lib/python3.3', ...]
/tmp/foo.py

を追加../../tmpしても正規化され、結果は同じになります。

しかし、使用PYTHONPATHする代わりに、いくつかの面白いパスを直接使用すると、原因と同じくらい面白い結果が得られます。

>>> import sys
>>> sys.path.append('../../tmp')
>>> import foo
['', '/usr/lib/python3.3', .... , '../../tmp']
../../tmp/foo.py

Guidoは上記のスレッドで、Pythonが絶対パスのすべてのエントリを変換しようとしない理由を説明しています。

すべてのインポートでgetpwd()を呼び出す必要はありません.... getpwd()は比較的低速であり、完全に失敗することがあります。

したがって、パスはそのまま使用さます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.