コード ベースのいくつかのテンプレート ファイルを現在のディレクトリにコピーする単純なヘルパー スクリプトを作成しています。ただし、テンプレートが保存されているディレクトリへの絶対パスはありません。スクリプトからの相対パスはありますが、スクリプトを呼び出すと、現在の作業ディレクトリからの相対パスとして扱われます。この相対 URL がスクリプトの場所からのものであることを指定する方法はありますか?
21 に答える
スクリプトを含むファイルで、次のようなことを行います。
import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
これにより、探しているファイルへの絶対パスが得られます。setuptools を使用している場合は、代わりにそのパッケージ リソース APIを使用する必要があることに注意してください。
更新: ここでコメントに返信しているので、コード サンプルを貼り付けることができます。:-)
常に利用できるとは限らないと考えるのは正しい
__file__
ですか (たとえば、ファイルをインポートするのではなく直接実行する場合)。
__main__
ファイルを直接実行することに言及するときは、スクリプトを意味していると思います。もしそうなら、私のシステムではそうではないようです(OS X 10.5.7のpython 2.5.1):
#foo.py
import os
print os.getcwd()
print __file__
#in the interactive interpreter
>>> import foo
/Users/jason
foo.py
#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py
__file__
ただし、 C 拡張機能にはいくつかの癖があることは知っています。たとえば、Mac でこれを行うことができます。
>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'
ただし、これにより、Windows マシンで例外が発生します。
必要ですos.path.realpath
(以下のサンプルでは、親ディレクトリをパスに追加します)
import sys,os
sys.path.append(os.path.realpath('..'))
私のコードを考えてみましょう:
import os
def readFile(filename):
filehandle = open(filename)
print filehandle.read()
filehandle.close()
fileDir = os.path.dirname(os.path.realpath('__file__'))
print fileDir
#For accessing the file in the same folder
filename = "same.txt"
readFile(filename)
#For accessing the file in a folder contained in the current folder
filename = os.path.join(fileDir, 'Folder1.1/same.txt')
readFile(filename)
#For accessing the file in the parent folder of the current folder
filename = os.path.join(fileDir, '../same.txt')
readFile(filename)
#For accessing the file inside a sibling folder.
filename = os.path.join(fileDir, '../Folder2/same.txt')
filename = os.path.abspath(os.path.realpath(filename))
print filename
readFile(filename)
sys.pathを参照してください。 プログラムの起動時に初期化されるため、このリストの最初の項目である path[0] は、Python インタープリターを呼び出すために使用されたスクリプトを含むディレクトリです。
このパスを、相対パスを適用するルート フォルダーとして使用します。
>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\\Python25\\Lib\\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\\Python25\\Lib\\idlelib\\path_to_libs'
使用する代わりに
import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
受け入れられた回答のように、使用する方がより堅牢です。
import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
__file__ を使用すると、モジュールがファイルからロードされた場合、モジュールがロードされたファイルが返されるため、スクリプトを含むファイルが別の場所から呼び出された場合、返されるディレクトリは正しくありません。
これらの回答は詳細を提供します: https://stackoverflow.com/a/31867043/5542253およびhttps://stackoverflow.com/a/50502/5542253
こんにちは、まず、関数os.path.abspath(path)およびos.path.relpath(path ) を理解する必要があります
つまり、 os.path.abspath(path)は絶対パスへの相対パスを作成します。また、指定されたパス自体が絶対パスである場合、関数は同じパスを返します。
同様にos.path.relpath(path)は相対パスへの絶対パスを作成します。指定されたパス自体が相対パスである場合、関数は同じパスを返します。
以下の例では、上記の概念を適切に理解できます。
私のpythonスクリプトによって処理される入力ファイルのリストを含むファイルinput_file_list.txtがあるとします。
D:\conc\input1.dic
D:\conc\input2.dic
D:\Copyioconc\input_file_list.txt
上記のフォルダ構成を見ると、input_file_list.txtはCopyofconcフォルダにあり、Python スクリプトで処理するファイルはconcフォルダにあります。
ただし、 input_file_list.txtファイルの内容は次のとおりです。
..\conc\input1.dic
..\conc\input2.dic
私のpythonスクリプトはD:ドライブにあります。
また、 input_file_list.txtファイルで提供される相対パスは、input_file_list.txtファイルのパスに対する相対パスです。
そのため、Python スクリプトが現在の作業ディレクトリを実行する場合(os.getcwd()を使用してパスを取得します)
私の相対パスはinput_file_list.txtからの相対パス、つまり"D:\Copyofconc"であるため、現在の作業ディレクトリを"D:\Copyofconc"に変更する必要があります。
したがって、os.chdir('D:\Copyofconc')を使用する必要があるため、現在の作業ディレクトリは"D:\Copyofconc"になります。
ファイルinput1.dicおよびinput2.dicを取得するには、「..\conc\input1.dic」という行を読み取り、次のコマンドを使用します。
input1_path= os.path.abspath('..\conc\input1.dic') (相対パスを絶対パスに変更します。ここでは、現在の作業ディレクトリが "D:\Copyofconc" であるため、ファイル ".\conc\input1. dic" は、"D:\Copyofconc" に対して相対的にアクセスする必要があります)
したがって、input1_pathは「D:\conc\input1.dic」になります。
An alternative which works for me:
this_dir = os.path.dirname(__file__)
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))
私にとってうまくいったのは、を使用することsys.path.insert
です。次に、移動する必要のあるディレクトリを指定しました。たとえば、1 つ上のディレクトリに移動する必要がありました。
import sys
sys.path.insert(0, '../')
から: C:\Users\xyz\myFolder
_C:\Users\xyz\testdata
import os
working_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# C:\Users\xyz\myFolder
print(working_dir)
updated_working_dir = os.path.join(os.path.realpath(working_dir + '/../'), 'testdata')
# C:\Users\xyz\testdata
print(updated_working_dir)
出力
C:\Users\xyz\myFolder
C:\Users\xyz\testdata