Buka file di lokasi relatif dengan Python

133

Misalkan kode python dieksekusi dalam tidak diketahui oleh direktori windows sebelumnya katakan 'utama', dan di mana pun kode diinstal ketika dijalankan perlu mengakses ke direktori 'main / 2091 / data.txt'.

bagaimana saya harus menggunakan fungsi buka (lokasi)? apa yang seharusnya menjadi lokasi?

Edit:

Saya menemukan bahwa di bawah ini kode sederhana akan berfungsi .. apakah ada kekurangannya?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
Bunga kamelia
sumber
1
Anda menggunakan garis miring terbalik yang tidak terhalang. Itu salah satu kelemahannya.
orip
6
Beberapa kelemahan. 1) Sesuai @orip, gunakan garis miring untuk path, bahkan di windows. Tali Anda tidak akan berfungsi. Atau gunakan string mentah seperti r"\2091\sample.txt". Atau melarikan diri mereka seperti "\\2091\\sample.txt"(tapi itu menjengkelkan). Juga, 2) Anda menggunakan getcwd () yang merupakan jalur yang Anda gunakan saat menjalankan skrip. Saya pikir Anda ingin relatif ke lokasi skrip (tapi sekarang bertanya-tanya). Dan 3), selalu gunakan os.pathfungsi untuk memanipulasi jalur. Jalur Anda bergabung dengan garis harus os.path.join(os.getcwd(), file)4); tidak ada gunanya
Russ
3
Dan untuk mengukur baik ... 5) penjaga penggunaan konteks untuk tetap bersih dan menghindari lupa untuk menutup file Anda: with open(path, 'r+') as fp:. Lihat di sini untuk penjelasan terbaik dari withpernyataan yang pernah saya lihat.
Russ
di samping perawatan yang diperlukan pada garis miring, seperti yang baru saja ditunjukkan, ada fungsi os.path.abspathuntuk mendapatkan jalur penuh dari jalur relatif untuk membuka dengan mudah. Pernyataan terakhir terlihat seperti ini:os.path.abspath('./2091/sample.txt')
OPMendeavor

Jawaban:

189

Dengan hal semacam ini Anda harus berhati-hati dengan direktori kerja Anda yang sebenarnya. Misalnya, Anda tidak boleh menjalankan skrip dari direktori tempat file itu berada. Dalam hal ini, Anda tidak bisa hanya menggunakan jalur relatif dengan sendirinya.

Jika Anda yakin file yang Anda inginkan ada di subdirektori di bawah tempat skrip sebenarnya berada, Anda dapat menggunakan __file__untuk membantu Anda di sini. __file__adalah jalur lengkap ke tempat skrip yang Anda jalankan berada.

Jadi Anda bisa bermain-main dengan sesuatu seperti ini:

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)
Russ
sumber
Saya menemukan bahwa di bawah ini kode sederhana akan berfungsi .. apakah ada kekurangannya? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = buka (path, 'r +'); <code>
@Arash Kerugiannya adalah cwd (direktori kerja saat ini) bisa apa saja, dan tidak akan selalu berada di tempat skrip Anda berada.
Cory Mawhorter
5
__file__adalah jalur relatif (setidaknya pada pengaturan saya, untuk beberapa alasan), dan Anda harus menelepon os.path.abspath(__file__)dulu. osx / homebrew 2.7
Cory Mawhorter
2
os.path.dirname ( file ) tidak berfungsi untuk saya di Python 2.7. Ini menunjukkanNameError: name '__file__' is not defined
Soumendra
1
@ Soumendra Saya pikir Anda mencobanya di konsol. Cobalah dalam file * .py.
Enku
35

Kode ini berfungsi dengan baik:

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)
Fahad Haleem
sumber
Bagi saya mengakses file di folder induk dari folder saat ini tidak berfungsi..yang .. ditambahkan sebagai string ..
M. Paul
Tidak berfungsi di Windows. Path ke file sudah benar tetapi Python menyatakan "file tidak ditemukan" dan menunjukkan path dengan pemisah \\.
lonstar
26

Saya membuat akun hanya supaya saya bisa menjelaskan perbedaan yang saya rasa saya temukan di respons asli Russ.

Sebagai referensi, jawaban aslinya adalah:

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

Ini adalah jawaban yang bagus karena mencoba secara dinamis membuat jalur sistem absolut ke file yang diinginkan.

Cory Mawhorter memperhatikan bahwa itu __file__adalah jalur relatif (juga pada sistem saya) dan disarankan menggunakan os.path.abspath(__file__). os.path.abspath, namun, mengembalikan jalur absolut dari skrip Anda saat ini (yaitu /path/to/dir/foobar.py)

Untuk menggunakan metode ini (dan bagaimana saya akhirnya bisa berfungsi) Anda harus menghapus nama skrip dari ujung jalan:

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 yang dihasilkan (dalam contoh ini) menjadi: /path/to/dir/2091/data.txt

Berikan Hulegaard
sumber
14
Anda bahkan dapat menggabungkan kedua pendekatan untuk yang lebih sederhanaos.path.dirname(os.path.abspath(__file__))
Luke Taylor
1
@LukeTaylor Memang itu akan lebih baik daripada mencoba mereplikasi os.path.dirnamefungsi sendiri seperti yang saya lakukan dalam jawaban saya tahun lalu.
Grant Hulegaard
19

Tergantung pada sistem operasi apa yang Anda gunakan. Jika Anda menginginkan solusi yang kompatibel dengan Windows dan * nix, sesuatu seperti:

from os import path

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

harus bekerja dengan baik.

The pathModul mampu memformat jalan untuk sistem operasi apapun itu berjalan pada. Juga, python menangani jalur relatif dengan baik, asalkan Anda memiliki izin yang benar.

Edit :

Seperti yang disebutkan oleh kindall dalam komentar, python dapat mengkonversi antara jalur unix-style dan windows-style, jadi kode yang lebih sederhana pun akan berfungsi:

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

Yang sedang berkata, pathmodul masih memiliki beberapa fungsi yang berguna.

Wilduck
sumber
3
relpath()mengonversi nama path ke jalur relatif. Karena ini sudah merupakan jalur relatif, itu tidak akan melakukan apa-apa.
kindall
Ini akan mengonversinya dari jalur gaya unix ke jalur gaya windows jika sesuai. Apakah ada fungsi lain dalam os.pathmodul yang akan menjadi pilihan yang lebih baik?
Wilduck
1
Windows sudah akan bekerja dengan baik dengan jalur gaya UNIX. Setidaknya seri berbasis NT akan (2000, XP, Vista, 7). Tidak perlu konversi.
kindall
7
Jawaban ini kurang tepat dan akan menimbulkan masalah. Path relatif secara default relatif terhadap direktori kerja saat ini (path tempat skrip dieksekusi), dan BUKAN lokasi skrip yang sebenarnya. Anda harus menggunakan __file__. Tolong lihat jawaban saya.
Russ
Apakah penulis jawaban ini membingungkan os.path.relpath dengan os.path.abspath?
foobarbecue
15

Saya menghabiskan banyak waktu untuk menemukan mengapa kode saya tidak dapat menemukan file saya menjalankan Python 3 pada sistem Windows. Jadi saya menambahkan. sebelum / dan semuanya bekerja dengan baik:

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')
Polo Ângelo
sumber
Lebih baik:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
Saya mencoba pada OS Windows tetapi saya tidak berhasil.
Ângelo Polotto
Menarik - dapatkah Anda mencetak script_dir? Kemudian putar ke jalur absolut seperti discript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
Saya akan coba itu, jika saya berhasil, saya akan mengubah jawabannya.
Ângelo Polotto
6

Kode:

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

Penjelasan:

Impor perpustakaan:

import os

Gunakan __file__untuk mencapai jalur skrip saat ini:

script_path = os.path.abspath(__file__)

Memisahkan jalur skrip menjadi beberapa item:

path_list = script_path.split(os.sep)

Hapus item terakhir dalam daftar (file skrip yang sebenarnya):

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

Tambahkan jalur file relatif:

rel_path = "main/2091/data.txt

Bergabunglah dengan item daftar, dan tambahkan file path relatif:

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

Sekarang Anda diatur untuk melakukan apa pun yang Anda inginkan dengan file tersebut, seperti, misalnya:

file = open(path)
Patriots299
sumber
Alih-alih path = "/".join(script_directory) + "/" + rel_pathAnda harus menggunakan modul os seperti pada path = os.path.join(script_directory, rel_path). Alih-alih secara manual mem-parsing jalan yang harus Anda gunakanscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
4

Coba ini:

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 memperkenalkan perpustakaan standar baru untuk menangani file dan jalur yang disebut pathlib. Ini bekerja untuk saya!

dcampo
sumber
3

Jika file ada di folder induk Anda, mis. follower.txt, Anda cukup menggunakanopen('../follower.txt', 'r').read()

Olivia Liao
sumber
2

Tidak yakin apakah ini berfungsi di mana-mana.

Saya menggunakan ipython di ubuntu.

Jika Anda ingin membaca file di sub-direktori folder saat ini:

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

skrip Anda ada di folder saat ini, coba saja ini:

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

Python hanya meneruskan nama file yang Anda berikan ke sistem operasi, yang membukanya. Jika sistem operasi Anda mendukung jalur relatif seperti main/2091/data.txt(petunjuk: ya), maka itu akan berfungsi dengan baik.

Anda mungkin menemukan bahwa cara termudah untuk menjawab pertanyaan seperti ini adalah dengan mencobanya dan melihat apa yang terjadi.

baik hati
sumber
2
Tidak benar ... direktori yang berfungsi di dalam skrip adalah lokasi Anda menjalankan skrip, bukan lokasi skrip. Jika Anda menjalankan skrip dari tempat lain (mungkin skrip ada di jalur sistem Anda) jalur relatif ke subdirektori tidak akan berfungsi. Silakan lihat jawaban saya tentang cara mengatasi ini.
Russ
@Russ - contoh OP menggunakan getcwd(). Saya membaca deskripsi asli sebagai "relatif terhadap tempat saya menjalankan skrip, di mana pun kode berada".
orip
@orip - OP menambahkan panggilan getcwd () 3 jam setelah pertanyaan. Tidak masalah ... pindah. :)
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.")
Webucator
sumber
0

Ketika saya masih pemula saya menemukan deskripsi ini agak menakutkan. Pada awalnya saya akan mencoba For Windows

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

dan ini akan menaikkan syntax error. Saya menggunakan banyak bingung. Lalu setelah beberapa berselancar di google. ditemukan mengapa kesalahan terjadi. Menulis ini untuk pemula

Itu karena untuk jalur yang akan dibaca di Unicode Anda cukup menambahkan \ketika memulai jalur file

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

Dan sekarang berfungsi, tambahkan saja \sebelum memulai direktori.

Chidhvilas
sumber
1
Garis miring terbalik adalah karakter pelarian untuk beberapa karakter. Jika Anda kebetulan menemukan \tseperti misalnya \top\directory, daripada '\ t' ditafsirkan sebagai karakter tab dan 'trik' Anda gagal. Pilihan terbaik adalah menggunakan format string mentah r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'yang tidak mencoba untuk 'melarikan diri' karakter.
Ronald