これは初心者の質問のように見えるかもしれませんが、そうではありません。いくつかの一般的なアプローチはすべての場合に機能しません:
これはpath = os.path.abspath(os.path.dirname(sys.argv[0]))
を使用することを意味しますが、別のディレクトリにある別のPythonスクリプトから実行している場合は機能せず、実際に発生する可能性があります。
これはpath = os.path.abspath(os.path.dirname(__file__))
を使用することを意味しますが、これは機能しないことがわかりました。
py2exe
には__file__
属性はありませんが、 回避策 がありますexecute()
を指定してIDLEから実行すると、__file__
属性はありませんNameError: global name '__file__' is not defined
が表示されます回答が不完全な関連質問:
私は、汎用ソリューションを探しています。これは、上記のすべてのユースケースで機能するものです。
テストケースの結果は次のとおりです。
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
#! /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")
#! /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
実行されているメインスクリプトの場所を直接判断することはできません。結局のところ、スクリプトがファイルからまったく生成されないことがありました。たとえば、対話型インタープリターや、メモリにのみ保存されている動的に生成されたコードから取得できます。
ただし、モジュールは常にファイルからロードされるため、モジュールの場所を確実に決定できます。次のコードを使用してモジュールを作成し、メインスクリプトと同じディレクトリに配置すると、メインスクリプトはモジュールをインポートし、それを使用して自分自身を見つけることができます。
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の複数のコピーが必要になる場合があります。
もちろん、スクリプトと同じ場所にあるモジュールをインポートできない他のツールによってメインスクリプトがロードされている場合は、運が悪いです。そのような場合、あなたが求めている情報はプログラムのどこにも存在しません。最善の策は、ツールの作成者にバグを報告することです。
まず、inspect
およびos
からインポートする必要があります
from inspect import getsourcefile
from os.path import abspath
次に、どこからでもソースファイルを見つけたい場合は、
abspath(getsourcefile(lambda:0))
私は同様の問題に直面していた、と私はこれが問題を解決するかもしれないと思う:
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__を使用します。
このソリューションは実行可能ファイルでも堅牢です
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
簡単な答えは、必要な情報を取得する保証された方法はないということですが、実際にはほとんど常に機能するヒューリスティックがあります。 Cで実行可能ファイルの場所を見つけるにはどうすればよいですかをご覧ください。 Cの観点から問題を説明しますが、提案されたソリューションはPythonに簡単に転写できます。
私の答えが信頼できない__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で現在実行されているファイルのパスを取得するにはどうすればよいですか の回答からのコードに基づいていました。
あなたは単に呼び出しました:
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()
はファイル名なしのディレクトリパスを返します。
これは、クロスプラットフォームの方法でトリックを実行する必要があります(インタープリターなどを使用していない限り)。
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には存在しないと聞いたため)。
スクリプトがシンボリックリンクである場合、リンク先のファイルのパス(シンボリックリンクのパスではなく)が提供されることに注意してください。
Path
モジュールのpathlib
を使用できます。
from pathlib import Path
# ...
Path(__file__)
parent
への呼び出しを使用して、パスをさらに進めることができます。
Path(__file__).parent
コードがファイルから来ている場合、そのフルネームを取得できます
sys._getframe().f_code.co_filename
関数名をf_code.co_name
として取得することもできます
私の解決策は次のとおりです。
import os
print(os.path.join(os.getcwd(), __file__))
以下を追加するだけです:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
または:
from sys import *
print(sys.argv[0])