私は、コードベースのいくつかのテンプレートファイルを現在のディレクトリにコピーするための簡単なヘルパースクリプトを作成しています。ただし、テンプレートが格納されているディレクトリへの絶対パスはわかりません。スクリプトからの相対パスはありますが、スクリプトを呼び出すと、それが現在の作業ディレクトリからの相対パスとして扱われます。この相対URLがスクリプトの場所からであることを指定する方法はありますか?
スクリプトを含むファイルでは、次のようにします。
import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
これにより、探しているファイルへの絶対パスがわかります。 setuptoolsを使用している場合は、おそらく代わりに package resources API を使用してください。
UPDATE:ここではコメントに返信しているので、コードサンプルを貼り付けることができます。 :-)
私は
__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
しかし、私は、Cの拡張機能に関して__file__
に関するいくつかの奇妙な点があることを知っています。たとえば、私の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
dir = os.path.dirname(__file__)
filename = os.path.join(dir, '/relative/path/to/file/you/want')
それを追加したいだけです
後者の文字列はバックスラッシュで始めることはできません。事実上、どの文字列もバックスラッシュを含むべきではありません。
それはのようなものでなければなりません
import os
dir = os.path.dirname(__file__)
filename = os.path.join(dir, 'relative','path','to','file','you','want')
受け入れられた答えは、場合によっては誤解を招く可能性があります。詳細については、 this linkを参照してください。
私のコードを見てください。
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'
2018年になり、Pythonは既に__future__
に進化しています。では、pathlib
、os.path
、os
、glob
などに苦労するのではなく、タスクを達成するためにPython 3.4に付属の驚くべき shutil
を使用してみてください。
したがって、ここには3つのパスがあります(重複している可能性があります)。
mod_path
:simple helper scriptのパスsrc_path
:これには、コピーを待機しているいくつかのテンプレートファイルが含まれています。cwd
:current directory、これらのテンプレートファイルの宛先。そして問題は:持っていないsrc_path
のフルパス、知っているmod_path
への相対パス。
これを驚くべき pathlib
で解決しましょう:
# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path
# `cwd`: current directory is straightforward
cwd = Path.cwd()
# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent
# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()
将来的には、まさにそれだけです。 :D
また、 pathlib
を使用して、これらのテンプレートファイルを選択、チェック、コピー/移動できます。
if src_path != cwd:
# When we have different types of files in the `src_path`
for template_path in src_path.glob('*.ini'):
fname = template_path.name
target = cwd / fname
if not target.exists():
# This is the COPY action
with target.open(mode='wb') as fd:
fd.write(template_path.read_bytes())
# If we want MOVE action, we could use:
# template_path.replace(target)
使用する代わりに
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/554225 そして https://stackoverflow.com/a/50502/554225
このコードはメインスクリプトへの絶対パスを返します。
import os
def whereAmI():
return os.path.dirname(os.path.realpath(__import__("__main__").__file__))
これはモジュール内でも機能します。
こんにちは最初にあなたは関数を理解する必要があります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"に対して相対的にアクセスされます。)
so input1_pathは "D:\ conc\input1.dic"になります
私のために働く代替手段:
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, '../')