Pythonの相対位置でファイルを開く


132

pythonコードが以前のWindowsディレクトリで知られていない 'main'で実行され、実行時にコードがインストールされている場合は、ディレクトリ 'main / 2091 / data.txt'にアクセスする必要があるとします。

open(location)関数をどのように使用すればよいですか?場所は何ですか?

編集:

以下の簡単なコードが機能することがわかりました..デメリットはありますか?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');

1
エスケープされていないバックスラッシュを使用しています。これは欠点の1つです。
orip

6
いくつかの欠点。1)@oripと同様に、Windowsでもパスにスラッシュを使用します。文字列は機能しません。またはのような生の文字列を使用しますr"\2091\sample.txt"。または、それらをエスケープします"\\2091\\sample.txt"(しかし、それは迷惑です)。また、2)スクリプトを実行したときのパスであるgetcwd()を使用しています。スクリプトの場所を基準にしてほしいと思っていました(しかし、今は疑問に思っています)。そして3)、常にos.pathパスを操作するための関数を使用します。パスを結ぶ線はos.path.join(os.getcwd(), file)4)でなければなりません。意味がない
Russ

3
そして、適切な対策として... 5)コンテキストガードを使用してクリーンに保ち、ファイルを閉じるのを忘れないようにしますwith open(path, 'r+') as fp:。私が見た声明の最も良い説明については、こちらをご覧くださいwith
Russ

先ほど示したように、スラッシュに必要な注意のほかに、os.path.abspath開く相対パスの完全パスを簡単に取得する関数があります。最後の文は次のようになりますos.path.abspath('./2091/sample.txt')
OPMendeavor

回答:


189

このタイプのものでは、実際の作業ディレクトリが何であるかに注意する必要があります。たとえば、ファイルがあるディレクトリからスクリプトを実行することはできません。この場合、相対パスを単独で使用することはできません。

必要なファイルが、スクリプトが実際に配置されているサブディレクトリの下にあることが確実な場合は、__file__ここを参考にしてください。 __file__実行中のスクリプトが配置されている場所へのフルパスです。

したがって、次のようなものをいじることができます。

import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

以下の簡単なコードが機能することがわかりました..デメリットはありますか?<pre> file = "\ sample.txt" path = os.getcwd()+ str(loc)+ file fp = open(path、 'r +'); <code>

@Arashこれの欠点は、cwd(現在の作業ディレクトリ)は何でもかまいませんが、必ずしもスクリプトが置かれている場所とは限りません。
Cory Mawhorter 2013

5
__file__相対パスであり(少なくとも、私のセットアップでは、何らかの理由で)、os.path.abspath(__file__)最初に呼び出す必要があります。osx / homebrew 2.7
Cory Mawhorter 2013

2
os.path.dirname(file)は、Python 2.7では動作しません。表示中NameError: name '__file__' is not defined
Soumendra

1
@Soumendra私はあなたがコンソールでそれを試みていると思います。* .pyファイルで試してください。
Enku

35

このコードは正常に動作します:

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)

私は現在のフォルダの親フォルダ内のファイルにアクセスするためのworked..the ..文字列として追加されていなかった...
M.ポール

Windowsでは機能しませんでした。ファイルへのパスは正しいですが、Pythonは「ファイルが見つかりません」と表示し、パスを\\区切り文字で示します。
lonstar

26

Russの最初の応答で見つけたと思う矛盾を明確にするために、アカウントを作成しました。

参考までに、彼の最初の答えは:

import os
script_dir = os.path.dirname(__file__)
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

目的のファイルへの絶対システムパスを動的に作成しようとしているため、これは素晴らしい答えです。

Cory Mawhorter __file__は、これが相対パスであることに気づき(私のシステムでも同様です)、の使用を提案しましたos.path.abspath(__file__)os.path.abspathただし、現在のスクリプトの絶対パスを返します(つまり/path/to/dir/foobar.py

この方法(および最終的にはどのように機能させるか)を使用するには、パスの末尾からスクリプト名を削除する必要があります。

import os
script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

結果のabs_file_path(この例では)は次のようになります。 /path/to/dir/2091/data.txt


14
両方のアプローチを組み合わせて、よりシンプルにすることもできますos.path.dirname(os.path.abspath(__file__))
Luke Taylor、

1
@LukeTaylor確かos.path.dirnameに、昨年の私の回答で行ったように、自分で機能を複製しようとするよりも良いでしょう。
Grant Hulegaard、2015

19

使用しているオペレーティングシステムによって異なります。Windowsと* nixの両方と互換性のあるソリューションが必要な場合:

from os import path

file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
    <do stuff>

正常に動作するはずです。

pathモジュールは、それが実行しているものは何でも、オペレーティングシステムのパスをフォーマットすることができます。また、適切な権限がある限り、Pythonは相対パスを適切に処理します。

編集

kindallがコメントで述べたように、Pythonはとにかくunixスタイルのパスとwindowsスタイルのパスの間で変換できるため、より単純なコードでも機能します。

with open("2091/data/txt") as f:
    <do stuff>

そうは言っても、pathモジュールにはまだいくつかの便利な機能があります。


3
relpath()パス名を相対パスに変換します。すでに相対パスなので、何もしません。
キンダル

必要に応じて、UNIXスタイルのパスからWindowsスタイルのパスに変換します。os.pathより良い選択となるモジュールに別の関数がありますか?
Wilduck

1
Windowsは、UNIXスタイルのパスですでに正常に動作します。少なくともNTベースのシリーズは(2000、XP、Vista、7)になります。変換は必要ありません。
キンダル

7
この答えは正確ではなく、問題を引き起こします。相対パスは、デフォルトでは現在の作業ディレクトリ(スクリプトの実行元のパス)からの相対パスであり、実際のスクリプトの場所ではありません。を使用する必要があります__file__。私の答えを見てください。
Russ

この回答の作成者は、os.path.relpathとos.path.abspathを混同しましたか?
foob​​arbecue

15

私はコードがWindowsシステムでPython 3を実行しているファイルを見つけられなかった理由を発見するために多くの時間を費やしています。だから私は追加しました。前に/すべてがうまくいった:

import os

script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, './output03.txt')
print(file_path)
fptr = open(file_path, 'w')

より良い:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D

私はそれをWindows OSで試しましたが、成功しませんでした。
アンジェロPolotto

興味深い-script_dirを出力できますか?次に、次のように絶対パスに変更しますscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D

私はそれを試みます、もし成功したら、私は答えを変えます。
アンジェロPolotto

6

コード:

import os
script_path = os.path.abspath(__file__) 
path_list = script_path.split(os.sep)
script_directory = path_list[0:len(path_list)-1]
rel_path = "main/2091/data.txt"
path = "/".join(script_directory) + "/" + rel_path

説明:

インポートライブラリ:

import os

__file__現在のスクリプトのパスを取得するために使用します。

script_path = os.path.abspath(__file__)

スクリプトパスを複数の項目に分離します。

path_list = script_path.split(os.sep)

リストの最後の項目(実際のスクリプトファイル)を削除します。

script_directory = path_list[0:len(path_list)-1]

相対ファイルのパスを追加します。

rel_path = "main/2091/data.txt

リスト項目を結合し、相対パスのファイルを追加します。

path = "/".join(script_directory) + "/" + rel_path

これで、たとえば次のように、ファイルに対して何でも実行するように設定されました。

file = open(path)

代わりに、のpath = "/".join(script_directory) + "/" + rel_pathようにosモジュールを使用する必要がありますpath = os.path.join(script_directory, rel_path)。使用するパスを手動で解析する代わりにscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D

3

ファイルが親フォルダにある場合。follower.txt、あなたは単に使うことができますopen('../follower.txt', 'r').read()


3

これを試して:

from pathlib import Path

data_folder = Path("/relative/path")
file_to_open = data_folder / "file.pdf"

f = open(file_to_open)

print(f.read())

Python 3.4では、pathlibと呼ばれるファイルとパスを処理するための新しい標準ライブラリが導入されました。わたしにはできる!


2

これがどこでも機能するかどうかはわかりません。

私はubuntuでipythonを使用しています。

現在のフォルダのサブディレクトリにあるファイルを読みたい場合:

/current-folder/sub-directory/data.csv

あなたのスクリプトは現在のフォルダーにありますこれを試してください:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)

1

Pythonは、指定したファイル名をオペレーティングシステムに渡し、それを開きます。オペレーティングシステムがmain/2091/data.txt(ヒント:サポートする)のような相対パスをサポートしている場合、それは問題なく機能します。

このような質問に答える最も簡単な方法は、実際に試して何が起こるかを確認することです。


2
そうではありません...スクリプト内の作業ディレクトリは、スクリプトの場所ではなく、スクリプトを実行した場所です。他の場所からスクリプトを実行する場合(おそらくスクリプトがシステムパスにある場合)、サブディレクトリへの相対パスは機能しません。これを回避する方法についての私の回答を参照してください。
Russ

@Russ-OPの例ではを使用していgetcwd()ます。元の説明を「コードがどこにあるかに関係なく、スクリプトを実行する場所を基準にして」と読みました。
orip

@orip-OPは、質問の3時間後にgetcwd()呼び出しを追加しました。とにかく...次へ。:)
Russ

1
import os
def file_path(relative_path):
    dir = os.path.dirname(os.path.abspath(__file__))
    split_path = relative_path.split("/")
    new_path = os.path.join(dir, *split_path)
    return new_path

with open(file_path("2091/data.txt"), "w") as f:
    f.write("Powerful you have become.")

0

私が初心者だったとき、私はこれらの説明が少し怖いことに気づきました。最初に私が試してみるように For Windows

f= open('C:\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f) 

そして、これはを発生させsyntax errorます。私はたくさん混乱しました。その後、グーグルでサーフィンした後。エラーが発生した理由を見つけました。初心者のためにこれを書く

これは、パスをUnicodeで読み取るために、\ファイルパスの開始時に単純にを追加するためです。

f= open('C:\\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f)

そして今それ\はディレクトリを開始する前に追加するだけで動作します。


1
バックスラッシュは、いくつかの文字のエスケープ文字です。\tたとえばに遭遇した場合\top\directory、「\ t」はタブ文字として解釈され、「トリック」は失敗します。最良のオプションは、文字r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'を「エスケープ」しない生の文字列形式を使用することです。
ロナルド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.