現在実行中のファイルのパスと名前を取得するにはどうすればよいですか?


482

他のスクリプトファイルを呼び出すスクリプトがありますが、プロセス内で現在実行されているファイルのファイルパスを取得する必要があります。

たとえば、3つのファイルがあるとします。execfileの使用:

  • script_1.pyを呼び出しますscript_2.py
  • 次に、をscript_2.py呼び出しますscript_3.py

どのように私は、ファイル名とパスを取得することができscript_3.py内のコードからscript_3.pyから引数としてその情報を渡すことなく、script_2.py

(実行するとos.getcwd()、現在のファイルではなく、元の開始スクリプトのファイルパスが返されます。)



2
os.path.realpath(file
Girish Gupta 2017

回答:


256

p1.py:

execfile("p2.py")

p2.py:

import inspect, os
print (inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # script directory

11
注意:この呼び出しは、異なる環境では同じ結果をもたらしません。以下のうさぎの回答を受け入れることを検討してください:stackoverflow.com/a/6628348/851398
ファラデー

3
@faraday:例を提供できますか?私は同様の質問を使っinspect.getabsfile()て答えました、そしてそれは私が試みたすべてのケースでうまくいきました。
jfs 2014

1
確かに@うさぎの答えは良いですか?
Dror

4
nah user13993はそれをはるかにうまく釘付けにした
osirisgothra '13 / 08/13

6
user13993は確かにそれを釘付けにしました。する必要がありますos.path.realpath(__file__)
uchuugaka 2015

566
__file__

他の人が言ったように。os.path.realpathを使用してシンボリックリンクを削除することもできます。

import os

os.path.realpath(__file__)

14
時々__file__'script_name.py'を返すこともあれば、 'script_name.pyc'を返すこともあるため、このアプローチには注意が必要です。したがって、出力は安定していません。
メカトロ

27
ただし、このファイルのパスは関係のないものだけを使用しているためです。
Uwe Koloska

5
これは奇妙です:コマンドライン "__file__"から引用符で囲んで(文字列として)実行すると、cmdの実行__file__ 元のディレクトリが提供されますが、(引用符なしでソースファイルへのパスが提供されます...理由
muon

7
@muonでは、渡されたファイル名の文字列が存在するかどうかのチェックは行われません。ファイルパスはcwdを基準にしているため、os.path.realpath関数はdirパスの一部であると想定します。 os.path.dirname(os.path.realpath(__file__))ファイルのあるディレクトリを返します。os.path.dirname(os.path.realpath("__file__"))cwdを返します。os.path.dirname(os.path.realpath("here_be_dragons"))cwdも返します。
ジェイミーブル

86

2018年11月28日更新:

Python 2と3での実験の要約を以下に示します。

main.py-foo.pyを実行します
foo.py-lib / bar.pyを実行しますlib / bar.py-
ファイルパス式を出力します

| Python | Run statement       | Filepath expression                    |
|--------+---------------------+----------------------------------------|
|      2 | execfile            | os.path.abspath(inspect.stack()[0][1]) |
|      2 | from lib import bar | __file__                               |
|      3 | exec                | (wasn't able to obtain it)             |
|      3 | import lib.bar      | __file__                               |

Python 2の場合、使用できるようにパッケージに切り替える方が明確かもしれません。2つのフォルダーにfrom lib import bar空の__init__.pyファイルを追加するだけです。

Python 3の場合、execfile存在しません- exec(open(<filename>).read())スタックフレームに影響しますが、最も近い代替はです。それはちょうど使用する最も簡単だimport fooimport lib.bar何も- __init__.pyファイルは必要ありません。

importとexecfileの違いもご覧ください。


元の回答:

これは、このスレッドでの回答に基づいた実験です-Windows上のPython 2.7.10。

スタックベースのものは、信頼できる結果を与えるように見える唯一のものです。最後の2つは最短の構文、つまり-

print os.path.abspath(inspect.stack()[0][1])                   # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib

これらが関数としてsysに追加されます!@Usagiと@pablogへのクレジット

次の3つのファイルに基づいて、main.pyをそのフォルダーから実行しますpython main.py(絶対パスを使用してexecfileを試し、別のフォルダーから呼び出します)。

C:\ filepaths \ main.py:execfile('foo.py')
C:\ filepaths \ foo.py:execfile('lib/bar.py')
C:\ filepaths \ lib \ bar.py:

import sys
import os
import inspect

print "Python " + sys.version
print

print __file__                                        # main.py
print sys.argv[0]                                     # main.py
print inspect.stack()[0][1]                           # lib/bar.py
print sys.path[0]                                     # C:\filepaths
print

print os.path.realpath(__file__)                      # C:\filepaths\main.py
print os.path.abspath(__file__)                       # C:\filepaths\main.py
print os.path.basename(__file__)                      # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print

print sys.path[0]                                     # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0])  # C:\filepaths
print os.path.dirname(os.path.abspath(__file__))      # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0]))  # C:\filepaths
print os.path.dirname(__file__)                       # (empty string)
print

print inspect.getfile(inspect.currentframe())         # lib/bar.py

print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print

print os.path.abspath(inspect.stack()[0][1])          # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1]))  # C:\filepaths\lib
print

72

私はこれがきれいだと思います:

import inspect
print inspect.stack()[0][1]

次と同じ情報を取得します。

print inspect.getfile(inspect.currentframe())

[0]はスタック内の現在のフレーム(スタックの最上部)であり、[1]はファイル名の場合、増加してスタックを後方に移動します。

print inspect.stack()[1][1]

現在のフレームを呼び出したスクリプトのファイル名になります。また、[-1]を使用すると、元の呼び出しスクリプトであるスタックの一番下に移動します。


4
タプル内の位置に依存することはお勧めしません。コードを読み取るときにどのデータを取得しようとしているのかは、まったく明確ではありません。
jpmc26

5
inspect.getfile()__file__モジュールオブジェクトが渡された場合、属性を返します。inspect.currentframe()モジュールを返します。エルゴ、これは高価な言い方です__file__
Martijn Pieters

inspect.stack()は、だけでなくinspect.currentframe()、かなり高価な関数でありinspect.getfile()、モジュールオブジェクトも呼び出します。
Martijn Pieters

42
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only

1
@Pat Notzのコメントを試してみました。ファイル名はから取得できます__file__
hlin117 2015

Python3ではos.path.dirname、スクリプトを実行している場所からの相対パスが表示されます。で例えばなり、スクリプトへの絶対パスではありません。私はabspathを探していましたが、スクリプトの名前を削除しました。sys.pathの最初の要素は明らかに答えです。python ../../test.pyos.path.dirname../../sys.path[0]
aerijman

37

スクリプトが1つのファイルのみで構成されている場合、ベストとマークされた提案はすべて真です。

モジュールとしてインポートされる可能性のあるファイルから実行可能ファイル(つまり、現在のプログラムのpythonインタープリターに渡されるルートファイル)の名前を確認する場合は、これを行う必要があります(これはファイルにあると仮定しましょう)foo.pyという名前):

import inspect

print inspect.stack()[-1][1]

[-1]スタックの最後のもの()が最初に入ったものだからです(スタックはLIFO / FILOデータ構造です)。

次に、ファイルにbar.pyあなたであればimport foo、それは印刷しますbar.pyのではなく、foo.pyこれらのすべての値であると思われます、:

  • __file__
  • inspect.getfile(inspect.currentframe())
  • inspect.stack()[0][1]

これは、日食のユニットテストのために、私は/home/user/Softwares/eclipse/plugins/org.python.pydev_4.5.5.201603221110/pysrcを得うまくなく動作します
hayj

2
これは高価なスペルの方法ですsys.modules['__main__'].__file__
Martijn Pieters

14
import os
print os.path.basename(__file__)

これはファイル名のみを提供します。つまり、ファイルのabspathがc:\ abcd \ abc.pyの場合、2行目はabc.pyを出力します


14

「プロセス内で現在実行されているファイルのファイルパス」が何を意味するかは完全には明確ではありません。 sys.argv[0]通常、Pythonインタープリターによって呼び出されたスクリプトの場所が含まれています。詳細については、sysのドキュメントを確認してください。

@Timと@Pat Notzが指摘したように、__ file__属性は

モジュールがロードされたファイル(モジュールがファイルからロードされた場合)


1
「print os.path.abspath(file)」と「print inspect.getfile(inspect.currentframe())」は、Pythonプログラムをwin32 exeに渡すと機能しません。sys.argv [0]のみが機能します!:)しかし、あなたは名前を取得するだけです!
aF。

11

Windows環境で動作する必要があるスクリプトがあります。このコードは、私が仕上げたものです:

import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])

それはかなりハックな決定です。しかし、それは外部ライブラリを必要とせず、私の場合、それは最も重要なことです。


1
これを行うには「os、sysをインポートする」必要がありましたが、これまでのところ、実際には文字列の最後にファイル名のないパスのみを返すのが最良の答えです。
emmagras 2014年


8
import os
os.path.dirname(os.path.abspath(__file__))

検査やその他のライブラリは必要ありません。

これは、インポートされたスクリプトと同じフォルダーにある構成ファイルを使用するスクリプト(実行されたスクリプトとは異なるディレクトリから)をインポートする必要があったときに、私にとってはうまくいきました。


現在の作業ディレクトリ(os.getcwd)がファイルが置かれているディレクトリと異なる場合、これは望ましい答えを生成しません。
アイアン枕2014

2
どうして?この場合、私には問題ありません。私は、ファイルが置かれているディレクトリを取得します。
マイケルMIOR

@IronPillow多分この答えはあなたが必要とするものであなたを助けるでしょう。stackoverflow.com/a/41546830/3123191
Kwuite


6
import sys

print sys.path[0]

これにより、現在実行中のスクリプトのパスが出力されます


2
sys.path [0]は非常に便利ですが、要求どおりにscript3ではなくscript1のパスを提供します
James

少なくともOS Xの2.7では、これが信頼できることはないと思います。同じファイルを直接実行すると機能します。repl、特に輸入された卵からは機能しません
uchuugaka


4

使用できます inspect.stack()

import inspect,os
inspect.stack()[0]  => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'

4

Python 3はかなり主流なので、pathlibファイルとパスの情報にアクセスするための優れたツールになっていると思うので、答えを含めたいと思いました。

from pathlib import Path

current_file: Path = Path(__file__).resolve()

現在のファイルのディレクトリを探す場合は.parentPath()ステートメントに追加するのと同じくらい簡単です。

current_path: Path = Path(__file__).parent.resolve()

3
import sys
print sys.argv[0]

10
残念ながら、これは、スクリプトがフルパスで呼び出された場合にのみ機能します。これは、スクリプトの呼び出しであるコマンドラインで「最初の引数」のみを返すためです。
cregox

2

これはうまくいくはずです:

import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))

2
print(__file__)
print(__import__("pathlib").Path(__file__).parent)

4
コードのみの回答はお勧めしません。これにより問題がどのように解決されるか、またはこれが既存の回答とどのように異なるかについて説明を追加してください。口コミより
ニック

1

実行中のスクリプトのディレクトリを取得するには

 print os.path.dirname( inspect.getfile(inspect.currentframe()))

1

私はいつもCurrent Working Directory(CWD)のos機能を使用してきました。これは標準ライブラリの一部であり、実装は非常に簡単です。次に例を示します。

    import os
    base_directory = os.getcwd()

1
提起された質問に当てはまるように回答を変更していただけますか この答えは質問には適用されません「私はパスと名前を取得するにはどうすればよい現在実行しているファイルのか?
マルコ・

1
これは、pythonコマンドを実行した場所からのパスを示します。そのためpython script.py、実際にpwdはLinuxでの実行と同じであるにもかかわらず、同じフォルダーでコマンドを実行すると機能するようです。
ジョージ

0

私は__file__でアプローチを使用しました
os.path.abspath(__file__)
が、少しトリックがあり、コードが最初に実行されたときに.pyファイルを返し、次の実行では* .pycファイルの名前を指定するため、次の
ようにしました:
inspect.getfile(inspect.currentframe())
または
sys._getframe().f_code.co_filename


0

私はeclipse デバッガーunittestを考慮した関数を書きました。起動した最初のスクリプトのフォルダーを返します。オプションで__file__変数を指定できますが、主なことは、この変数をすべての呼び出し階層で共有する必要がないことです。

私が見なかった特定のケースをスタックして他のスタックを処理できるかもしれませんが、私にとっては問題ありません。

import inspect, os
def getRootDirectory(_file_=None):
    """
    Get the directory of the root execution file
    Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
    For eclipse user with unittest or debugger, the function search for the correct folder in the stack
    You can pass __file__ (with 4 underscores) if you want the caller directory
    """
    # If we don't have the __file__ :
    if _file_ is None:
        # We get the last :
        rootFile = inspect.stack()[-1][1]
        folder = os.path.abspath(rootFile)
        # If we use unittest :
        if ("/pysrc" in folder) & ("org.python.pydev" in folder):
            previous = None
            # We search from left to right the case.py :
            for el in inspect.stack():
                currentFile = os.path.abspath(el[1])
                if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
                    break
                previous = currentFile
            folder = previous
        # We return the folder :
        return os.path.dirname(folder)
    else:
        # We return the folder according to specified __file__ :
        return os.path.dirname(os.path.realpath(_file_))

0

プラットフォーム間(macOS / Windows / Linux)で移行の一貫性を保つには、次のことを試してください。

path = r'%s' % os.getcwd().replace('\\','/')


2
これは間違っています。これにより、現在のパスは取得されますが、現在のファイルのパスは取得されません。
Charles Plager 2018年

0

最も簡単な方法は次のとおりです。

script_1.py:

import subprocess
subprocess.call(['python3',<path_to_script_2.py>])

script_2.py:

sys.argv[0]

PS:試しましたがexecfile、script_2.pyを文字列として読み取るため、がsys.argv[0]返され<string>ます。


0

ここに私が使用するものがありますので、問題なくコードをどこにでも投げることができます。__name__は常に定義され__file__ますが、コードがファイルとして実行された場合にのみ定義されます(IDLE / iPythonでは実行されません)。

    if '__file__' in globals():
        self_name = globals()['__file__']
    elif '__file__' in locals():
        self_name = locals()['__file__']
    else:
        self_name = __name__

または、次のように書くこともできます。

self_name = globals().get('__file__', locals().get('__file__', __name__))

-2

これらの回答のほとんどは、Pythonバージョン2.x以前で作成されました。Python 3.xでは、print関数の構文が変更され、括弧、つまりprint()が必要になりました。

したがって、Python 2.xのuser13993からの以前のハイスコアの回答は次のとおりです。

import inspect, os
print inspect.getfile(inspect.currentframe()) # script filename (usually with path)
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # script directory

Python 3.xになる:

import inspect, os
print(inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) ) # script directory

-3

もしファイル名なしで欲しい./か、.pyこれを試すことができるなら

filename = testscript.py
file_name = __file__[2:-3]

file_name []内のインデックスを変更することで、必要なものを生成できるテストスクリプトを出力します


-3
import os

import wx


# return the full path of this file
print(os.getcwd())

icon = wx.Icon(os.getcwd() + '/img/image.png', wx.BITMAP_TYPE_PNG, 16, 16)

# put the icon on the frame
self.SetIcon(icon)

7
os.getcwd()は、現在実行中のファイルのディレクトリではなく、PROCESSの現在のWORKINGディレクトリを返します。これは正しい結果を返すように見えるかもしれませんが、結果が現在のファイルの親ディレクトリでない場合がたくさんあります。上記のようにos.path.dirname(file)を使用する方がはるかに良いです。
サマスピン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.