Dosyayı Python'da göreceli bir konumda açın


133

Python kodunun önceki Windows dizini tarafından bilinmeyen bir yerde çalıştırıldığını varsayalım. 'Main' deyin ve kod çalıştırıldığında her nerede kurulursa, 'main / 2091 / data.txt' dizinine erişmesi gerekir.

open (konum) işlevini nasıl kullanmalıyım? konum ne olmalı?

Düzenle :

Aşağıdaki basit kodun işe yarayacağını buldum .. herhangi bir dezavantajı var mı?

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

1
Çıkış karaktersiz ters eğik çizgi kullanıyorsunuz. Bu bir dezavantaj.
orip

6
Birkaç dezavantaj. 1) @orip'e göre, pencerelerde bile yollar için eğik çizgi kullanın. İpiniz çalışmayacak. Veya gibi ham dizeler kullanın r"\2091\sample.txt". Ya da onlardan kaçının "\\2091\\sample.txt"(ama bu can sıkıcıdır). Ayrıca, 2) betiği çalıştırırken içinde bulunduğunuz yol olan getcwd () kullanıyorsunuz. Senaryo konumuna göre istediğini sanıyordum (ama şimdi merak ediyorum). Ve 3), os.pathyolları değiştirmek için daima işlevleri kullanın . Hat birleştirme yolunuz os.path.join(os.getcwd(), file)4) olmalıdır ; anlamsız
Russ

3
Ve iyi ölçmek için ... 5) kullanım bağlam korumalar temiz tutmak ve dosyayı kapatmak unutmak önlemek için: with open(path, 'r+') as fp:. Gördüğüm ifadelerin en iyi açıklaması için buraya bakın with.
Russ

Az önce belirtildiği gibi, eğik çizgilere gereken özen göstermenin yanı sıra, os.path.abspathaçılacak göreceli yolun tam yolunu kolayca elde etme işlevi vardır . final açıklaması şöyle görünüyor:os.path.abspath('./2091/sample.txt')
OPMendeavor

Yanıtlar:


189

Bu tür şeylerde asıl çalışma dizininizin ne olduğuna dikkat etmeniz gerekir. Örneğin, komut dosyasını dosyanın bulunduğu dizinden çalıştıramazsınız. Bu durumda, yalnızca göreli bir yolu tek başına kullanamazsınız.

İstediğiniz dosyanın betiğin bulunduğu yerin altındaki bir alt dizinde olduğundan eminseniz, burada size __file__yardımcı olmak için kullanabilirsiniz . __file__çalıştırdığınız komut dosyasının bulunduğu tam yoldur.

Böylece böyle bir şeyle oynayabilirsiniz:

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)

Aşağıdaki basit kodun çalışacağını buldum .. herhangi bir dezavantajı var mı? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>

@Arash Bunun dezavantajı, cwd (mevcut çalışma dizini) herhangi bir şey olabilir ve betiğinizin bulunduğu yerde olması gerekmez.
Cory Mawhorter

5
__file__göreceli bir yoldur (en azından benim kurulumumda, bir nedenle) ve os.path.abspath(__file__)önce aramanız gerekir . osx / homebrew 2.7
Cory Mawhorter

2
os.path.dirname ( dosya ) Python 2.7'de benim için çalışmıyor. Bu gösteriyorNameError: name '__file__' is not defined
Soumendra

1
@Soumendra Sanırım konsolda deniyorsun. Bir * .py dosyasında deneyin.
Enku

35

Bu kod iyi çalışıyor:

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)

Benim için geçerli klasörün üst klasöründeki dosyaya erişmem işe yaramadı ... dize olarak eklendi ..
M. Paul

Windows'ta çalışmadı. Dosyanın yolu doğru, ancak Python "dosya bulunamadı" diyor ve \\ ayırıcılarla yolu gösteriyor.
lonstar

26

Russ'ın orijinal cevabında bulduğumu düşündüğüm bir tutarsızlığı açıklığa kavuşturabilmek için bir hesap oluşturdum.

Referans için, orijinal cevabı şuydu:

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

Bu harika bir cevap çünkü dinamik olarak istenen dosyaya giden mutlak bir sistem yolu oluşturmaya çalışıyor.

Cory Mawhorter __file__, bunun göreceli bir yol olduğunu fark etti (benim sistemimde de geçerli) ve kullanılması önerildi os.path.abspath(__file__). os.path.abspath, ancak, mevcut betiğinizin mutlak yolunu döndürür (yani /path/to/dir/foobar.py)

Bu yöntemi (ve sonunda onu nasıl çalıştırdığımı) kullanmak için komut dosyası adını yolun sonundan kaldırmanız gerekir:

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)

Elde edilen abs_file_path (bu örnekte) şöyle olur: /path/to/dir/2091/data.txt


14
Hatta daha basit için her iki yaklaşımı birleştirebilirsinizos.path.dirname(os.path.abspath(__file__))
Luke Taylor

1
@LukeTaylor Bu, os.path.dirnamegeçen yıl cevabımda yaptığım gibi işlevselliği kendiniz kopyalamaya çalışmaktan daha iyi olurdu .
Grant Hulegaard

19

Hangi işletim sistemini kullandığınıza bağlıdır. Hem Windows hem de * nix ile uyumlu bir çözüm istiyorsanız, örneğin:

from os import path

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

iyi çalışmalı.

pathModül üzerinde çalıştığı ne olursa olsun işletim sistemi için bir yol biçimlendirmek yapabiliyor. Ayrıca, doğru izinlere sahip olduğunuz sürece, python göreceli yolları gayet iyi işler.

Düzenle :

Kindall tarafından yorumlarda belirtildiği gibi, python yine de unix tarzı ve Windows tarzı yollar arasında dönüşüm yapabilir, bu nedenle daha basit kod bile çalışacaktır:

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

Bununla birlikte, pathmodülün hala bazı yararlı işlevleri vardır.


3
relpath()bir yol adını göreceli bir yola dönüştürür. Zaten göreceli bir yol olduğu için hiçbir şey yapmaz.
kindall

Uygunsa, onu unix tarzı bir yoldan Windows stili yola dönüştürecektir. Modülde os.pathdaha iyi bir seçim olabilecek başka bir işlev var mı ?
Wilduck

1
Windows zaten UNIX tarzı bir yolla düzgün çalışacaktır. En azından NT tabanlı seriler olacaktır (2000, XP, Vista, 7). Dönüştürmeye gerek yok.
kindall

7
Bu cevap tam olarak doğru değil ve sorunlara neden olacak. Göreli yollar varsayılan olarak geçerli çalışma dizinine (betiğin yürütüldüğü yol) ilişkilidir ve gerçek kod konumu DEĞİLDİR. Kullanmanız gerekiyor __file__. Lütfen cevabıma bakın.
Russ

Bu cevabın yazarı os.path.relpath'i os.path.abspath ile karıştırdı mı?
foobarbecue

15

Kodumun Windows sisteminde Python 3 çalıştıran dosyamı neden bulamadığını keşfetmek için çok zaman harcıyorum. Ben de ekledim. önce / ve her şey yolunda gitti:

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')

Daha iyi:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D

Bunu Windows işletim sisteminde denedim ama başarılı olamadım.
Ângelo Polotto

İlginç - script_dir yazdırabilir misiniz? Sonra onu mutlak yola çevirinscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D

Deneyeceğim, başarırsam cevabı değiştireceğim.
Ângelo Polotto

6

Kod:

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

Açıklama:

Kitaplığı içe aktar:

import os

__file__Mevcut betiğin yolunu elde etmek için kullanın :

script_path = os.path.abspath(__file__)

Komut dosyası yolunu birden çok öğeye ayırır:

path_list = script_path.split(os.sep)

Listedeki son öğeyi kaldırın (gerçek komut dosyası):

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

Göreli dosyanın yolunu ekleyin:

rel_path = "main/2091/data.txt

Liste öğelerini birleştirin ve göreli yol dosyasını ekleyin:

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

Artık dosya ile istediğinizi yapmaya hazırsınız, örneğin:

file = open(path)

Bunun yerine path = "/".join(script_directory) + "/" + rel_pathos modülünü olduğu gibi kullanmalısınız path = os.path.join(script_directory, rel_path). Kullanmanız gereken yolu manuel olarak ayrıştırmak yerinescript_path = os.path.dirname(__file__)
Mr_and_Mrs_D

4

Bunu dene:

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 adı verilen dosyalar ve yollarla ilgilenmek için yeni bir standart kitaplık tanıttı. Benim için çalışıyor!


3

Dosya üst klasörünüzdeyse, örn. follower.txt, kullanabilirsinizopen('../follower.txt', 'r').read()


2

Bunun her yerde işe yarayıp yaramadığından emin değilim.

Ubuntu'da ipython kullanıyorum.

Mevcut klasörün alt dizinindeki dosyayı okumak istiyorsanız:

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

betiğiniz geçerli klasörde sadece şunu deneyin:

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

1

Python, verdiğiniz dosya adını işletim sistemine aktarır ve onu açar. İşletim sisteminiz main/2091/data.txt(ipucu: öyle) gibi göreli yolları destekliyorsa , bu iyi çalışacaktır.

Böyle bir soruyu yanıtlamanın en kolay yolunun denemek ve ne olacağını görmek olduğunu fark edebilirsiniz.


2
Doğru değil ... bir komut dosyası içindeki çalışma dizini, komut dosyasını çalıştırdığınız konumdur, komut dosyasının konumu değil . Komut dosyasını başka bir yerden çalıştırırsanız (belki komut dosyası sistem yolunuzda olabilir), alt dizine giden göreceli yol çalışmayacaktır. Lütfen bunun üstesinden nasıl gelineceği konusundaki cevabıma bakın.
Russ

@Russ - OP'nin örneği kullanır getcwd(). Orijinal açıklamayı "kodun nerede olduğuna bakılmaksızın komut dosyasını çalıştırdığım yere göre" olarak okudum.
orip

@orip - OP, sorudan 3 saat sonra getcwd () çağrısını ekledi. Fark etmez ... devam et. :)
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

Başlangıç ​​seviyesindeyken bu açıklamaları biraz korkutucu buldum. İlk başta deneyeceğim gibi For Windows

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

ve bu bir syntax error. Kafam çok karıştı. Sonra Google'da biraz gezindikten sonra. hatanın neden oluştuğunu buldu. Bunu yeni başlayanlar için yazmak

Unicode'da okunacak yol için \dosya yolunu başlatırken basit bir şekilde a eklemeniz

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

Ve şimdi \dizini başlatmadan önce sadece ekle çalışıyor .


1
Ters eğik çizgiler, birkaç karakter için kaçış karakterleridir. Eğer karşılaşma edersek \törneğin gibi \top\directory, '\' t sekme karakteri ve 'hile' olarak yorumlanır daha başarısız olur. En iyi seçenek, r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'karakterlerden 'kaçış' yapmaya çalışmayan ham dize biçimini kullanmaktır .
Ronald
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.