web-dev-qa-db-ja.com

Pythonで現在実行されているファイルのパスを取得するにはどうすればよいですか?

これは初心者の質問のように見えるかもしれませんが、そうではありません。いくつかの一般的なアプローチはすべての場合に機能しません:

sys.argv [0]

これはpath = os.path.abspath(os.path.dirname(sys.argv[0]))を使用することを意味しますが、別のディレクトリにある別のPythonスクリプトから実行している場合は機能せず、実際に発生する可能性があります。

__ファイル__

これはpath = os.path.abspath(os.path.dirname(__file__))を使用することを意味しますが、これは機能しないことがわかりました。

  • py2exeには__file__属性はありませんが、 回避策 があります
  • execute()を指定してIDLEから実行すると、__file__属性はありません
  • OS X 10.6でNameError: global name '__file__' is not definedが表示されます

回答が不完全な関連質問:

私は、汎用ソリューションを探しています。これは、上記のすべてのユースケースで機能するものです。

更新

テストケースの結果は次のとおりです。

python a.pyの出力(Windowsの場合)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

a.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

subdir/b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

C:.
|   a.py
\---subdir
        b.py
176
sorin

実行されているメインスクリプトの場所を直接判断することはできません。結局のところ、スクリプトがファイルからまったく生成されないことがありました。たとえば、対話型インタープリターや、メモリにのみ保存されている動的に生成されたコードから取得できます。

ただし、モジュールは常にファイルからロードされるため、モジュールの場所を確実に決定できます。次のコードを使用してモジュールを作成し、メインスクリプトと同じディレクトリに配置すると、メインスクリプトはモジュールをインポートし、それを使用して自分自身を見つけることができます。

some_path/module_locator.py:

def we_are_frozen():
    # All of the modules are built-in to the interpreter, e.g., by py2exe
    return hasattr(sys, "frozen")

def module_path():
    encoding = sys.getfilesystemencoding()
    if we_are_frozen():
        return os.path.dirname(unicode(sys.executable, encoding))
    return os.path.dirname(unicode(__file__, encoding))

some_path/main.py:

import module_locator
my_path = module_locator.module_path()

異なるディレクトリに複数のメインスクリプトがある場合、module_locatorの複数のコピーが必要になる場合があります。

もちろん、スクリプトと同じ場所にあるモジュールをインポートできない他のツールによってメインスクリプトがロードされている場合は、運が悪いです。そのような場合、あなたが求めている情報はプログラムのどこにも存在しません。最善の策は、ツールの作成者にバグを報告することです。

78

まず、inspectおよびosからインポートする必要があります

from inspect import getsourcefile
from os.path import abspath

次に、どこからでもソースファイルを見つけたい場合は、

abspath(getsourcefile(lambda:0))
55
ArtOfWarfare

私は同様の問題に直面していた、と私はこれが問題を解決するかもしれないと思う:

def module_path(local_function):
   ''' returns the module path without the use of __file__.  Requires a function defined
   locally in the module.
   from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
   return os.path.abspath(inspect.getsourcefile(local_function))

通常のスクリプトおよびアイドル状態で機能します。私が言えるのは、他の人に試してみることだけです!

私の典型的な使用法:

from toolbox import module_path
def main():
   pass # Do stuff

global __modpath__
__modpath__ = module_path(main)

ここで、__ file__の代わりに__modpath__を使用します。

14
Garrett Berg

このソリューションは実行可能ファイルでも堅牢です

import inspect, os.path

filename = inspect.getframeinfo(inspect.currentframe()).filename
path     = os.path.dirname(os.path.abspath(filename))
10

簡単な答えは、必要な情報を取得する保証された方法はないということですが、実際にはほとんど常に機能するヒューリスティックがあります。 Cで実行可能ファイルの場所を見つけるにはどうすればよいですかをご覧ください。 Cの観点から問題を説明しますが、提案されたソリューションはPythonに簡単に転写できます。

6
Dale Hagglund

私の答えが信頼できない__file__変数を使用しない理由を含む関連情報については、質問への私の答え 親フォルダーからのモジュールのインポート を参照してください。モジュールosおよびinspectはPythonの一部として提供されるため、この単純なソリューションは異なるオペレーティングシステムとの相互互換性が必要です。

最初に、inspectおよびosモジュールの一部をインポートする必要があります。

from inspect import getsourcefile
from os.path import abspath

次に、Pythonコードで必要な他の場所で次の行を使用します。

abspath(getsourcefile(lambda:0))

使い方:

組み込みモジュールos(以下の説明)から、abspathツールがインポートされます。

使用しているシステムに応じて、Mac、NT、またはPosixのOSルーチン。

次に、getsourcefile(以下の説明)が組み込みモジュールinspectからインポートされます。

ライブPythonオブジェクトから有用な情報を取得します。

  • abspath(path)は、ファイルパスの絶対/完全バージョンを返します
  • getsourcefile(lambda:0)はラムダ関数オブジェクトの内部ソースファイルを何らかの方法で取得するため、Pythonシェルで'<pyshell#nn>'を返すか、現在Pythonコードのファイルパスを返します実行されています。

getsourcefile(lambda:0)の結果でabspathを使用すると、生成されるファイルパスがPythonファイルの完全なファイルパスであることを確認する必要があります。
この説明されたソリューションは、もともと Pythonで現在実行されているファイルのパスを取得するにはどうすればよいですか の回答からのコードに基づいていました。

4
Edward

あなたは単に呼び出しました:

path = os.path.abspath(os.path.dirname(sys.argv[0]))

の代わりに:

path = os.path.dirname(os.path.abspath(sys.argv[0]))

abspath()sys.argv[0](コードのファイル名)の絶対パスを提供し、dirname()はファイル名なしのディレクトリパスを返します。

3
dgbcgx

これは、クロスプラットフォームの方法でトリックを実行する必要があります(インタープリターなどを使用していない限り)。

import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))

sys.path[0]は、呼び出し元のスクリプトがあるディレクトリです(最初の場所は、そのスクリプトで使用されるモジュールを探します)。ファイル自体の名前をsys.argv[0]の末尾から取り去ることができます(これはos.path.basenameで行ったことです)。 os.path.joinは、クロスプラットフォームでそれらを結び付けるだけです。 os.path.realpathは、スクリプト自体とは異なる名前のシンボリックリンクを取得する場合に、スクリプトの実際の名前を取得することを確認します。

私はMacを持っていません。そのため、私はこれをテストしていません。正常に機能するかどうかをお知らせください。これをLinux(Xubuntu)でPython 3.4でテストしました。この問題の多くの解決策はMacでは動作しないことに注意してください(__file__はMacには存在しないと聞いたため)。

スクリプトがシンボリックリンクである場合、リンク先のファイルのパス(シンボリックリンクのパスではなく)が提供されることに注意してください。

2
Shule

Pathモジュールのpathlibを使用できます。

from pathlib import Path

# ...

Path(__file__)

parentへの呼び出しを使用して、パスをさらに進めることができます。

Path(__file__).parent
2
Gavriel Cohen

コードがファイルから来ている場合、そのフルネームを取得できます

sys._getframe().f_code.co_filename

関数名をf_code.co_nameとして取得することもできます

1
Alex Cohn

私の解決策は次のとおりです。

import os
print(os.path.join(os.getcwd(), __file__))
0
ThienSuBS

以下を追加するだけです:

from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)

または:

from sys import *
print(sys.argv[0])
0
H. Kamran