Otwórz plik we względnej lokalizacji w Pythonie

132

Załóżmy, że kod Pythona jest wykonywany w nieznanym wcześniej katalogu Windows, na przykład „main”, a gdziekolwiek kod jest instalowany po uruchomieniu, musi mieć dostęp do katalogu „main / 2091 / data.txt”.

jak używać funkcji open (location)? jaka powinna być lokalizacja?

Edytować :

Okazało się, że poniżej prosty kod będzie działał… czy ma jakieś wady?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
Kamelia
źródło
1
Używasz odwrotnych ukośników bez zmiany znaczenia. To jedna wada.
orip
6
Kilka wad. 1) Zgodnie z @orip, użyj ukośników dla ścieżek, nawet w oknach. Twój sznurek nie zadziała. Lub użyj surowych ciągów, takich jak r"\2091\sample.txt". Lub uciekaj im jak "\\2091\\sample.txt"(ale to jest denerwujące). Ponadto, 2) używasz getcwd (), czyli ścieżki, w której znajdowałeś się podczas wykonywania skryptu. Myślałem, że chcesz w odniesieniu do lokalizacji skryptu (ale teraz się zastanawiam). I 3), zawsze używaj os.pathfunkcji do manipulowania ścieżkami. Linia łącząca twoją ścieżkę powinna być os.path.join(os.getcwd(), file)4) the; nie ma sensu
Russ
3
I na dokładkę ... 5) osłony kontekst stosowanie do utrzymania w czystości i uniknąć zapominając zamknąć plik: with open(path, 'r+') as fp:. Zobacz tutaj, aby uzyskać najlepsze wyjaśnienie withstwierdzeń, jakie widziałem.
Russ
Oprócz niezbędnej dbałości o ukośniki, jak właśnie wskazano, istnieje funkcja os.path.abspathumożliwiająca łatwe uzyskanie pełnej ścieżki względnej ścieżki do otwarcia. końcowe oświadczenie wygląda następująco:os.path.abspath('./2091/sample.txt')
OPMendeavour

Odpowiedzi:

189

Przy tego typu rzeczach musisz uważać, jaki jest twój rzeczywisty katalog roboczy. Na przykład, nie możesz uruchomić skryptu z katalogu, w którym znajduje się plik. W takim przypadku nie możesz po prostu użyć samej ścieżki względnej.

Jeśli jesteś pewien, że żądany plik znajduje się w podkatalogu poniżej miejsca, w którym faktycznie znajduje się skrypt, możesz tutaj __file__pomóc. __file__to pełna ścieżka do miejsca, w którym znajduje się uruchamiany skrypt.

Możesz więc bawić się czymś takim:

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
źródło
Okazało się, że poniżej prosty kod będzie działał… czy ma jakieś wady? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>
@Arash Wadą jest to, że cwd (bieżący katalog roboczy) może być wszystkim i niekoniecznie musi znajdować się tam, gdzie znajduje się twój skrypt.
Cory Mawhorter
5
__file__jest ścieżką względną (przynajmniej w mojej konfiguracji, z jakiegoś powodu) i musisz os.path.abspath(__file__)najpierw zadzwonić . osx / homebrew 2.7
Cory Mawhorter
2
os.path.dirname ( plik ) nie działa dla mnie w Pythonie 2.7. To pokazujeNameError: name '__file__' is not defined
Soumendra
1
@Soumendra Myślę, że próbujesz tego w konsoli. Wypróbuj w pliku * .py.
Enku
35

Ten kod działa dobrze:

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
źródło
U mnie nie udało się uzyskać dostępu do pliku w folderze nadrzędnym bieżącego folderu .. .. jest dodawane jako ciąg znaków ..
M. Paul
Nie działa w systemie Windows. Ścieżka do pliku jest poprawna, ale Python stwierdza: „nie znaleziono pliku” i pokazuje ścieżkę z separatorami \\.
lonstar
26

Utworzyłem konto tylko po to, by wyjaśnić rozbieżność, którą moim zdaniem znalazłem w oryginalnej odpowiedzi Russa.

Dla porównania, jego pierwotna odpowiedź brzmiała:

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

To świetna odpowiedź, ponieważ próbuje dynamicznie utworzyć bezwzględną ścieżkę systemową do żądanego pliku.

Cory Mawhorter zauważył, że __file__jest to ścieżka względna (jest również w moim systemie) i zasugerował użycie os.path.abspath(__file__). os.path.abspathjednak zwraca bezwzględną ścieżkę do bieżącego skryptu (tj. /path/to/dir/foobar.py)

Aby użyć tej metody (i jak ostatecznie ją uruchomiłem), musisz usunąć nazwę skryptu z końca ścieżki:

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)

Wynikowy abs_file_path (w tym przykładzie) staje się: /path/to/dir/2091/data.txt

Grant Hulegaard
źródło
14
Możesz nawet połączyć oba podejścia dla prostszegoos.path.dirname(os.path.abspath(__file__))
Luke Taylor
1
@LukeTaylor Rzeczywiście, byłoby to lepsze niż próba samodzielnego odtworzenia os.path.dirnamefunkcjonalności, tak jak to zrobiłem w mojej odpowiedzi w zeszłym roku.
Grant Hulegaard
19

To zależy od używanego systemu operacyjnego. Jeśli potrzebujesz rozwiązania, które jest kompatybilne zarówno z Windows, jak i * nix, coś takiego:

from os import path

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

powinno działać dobrze.

pathModuł jest w stanie sformatować ścieżkę niezależnie od systemu operacyjnego jest uruchomiony na. Ponadto Python radzi sobie dobrze ze ścieżkami względnymi, o ile masz odpowiednie uprawnienia.

Edycja :

Jak wspomniał kindall w komentarzach, Python i tak może konwertować między ścieżkami w stylu unix i w stylu okien, więc nawet prostszy kod będzie działał:

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

Mimo to pathmoduł nadal ma kilka przydatnych funkcji.

Wilduck
źródło
3
relpath()konwertuje nazwę ścieżki na ścieżkę względną. Ponieważ jest to już ścieżka względna, nic nie da.
kindall
W razie potrzeby przekonwertuje go ze ścieżki w stylu uniksowym na ścieżkę w stylu okna. Czy w os.pathmodule jest inna funkcja , która byłaby lepszym wyborem?
Wilduck
1
Windows będzie już działał dobrze ze ścieżką w stylu UNIX. Przynajmniej seria oparta na NT (2000, XP, Vista, 7). Nie jest konieczna żadna konwersja.
kindall
7
Ta odpowiedź nie jest do końca poprawna i spowoduje problemy. Ścieżki względne są domyślnie względne w stosunku do bieżącego katalogu roboczego (ścieżka, z której skrypt został wykonany), a NIE rzeczywistej lokalizacji skryptu. Musisz użyć __file__. Zobacz moją odpowiedź.
Russ
Czy autor tej odpowiedzi pomylił os.path.relpath z os.path.abspath?
foobarbecue
15

Spędziłem dużo czasu, aby odkryć, dlaczego mój kod nie mógł znaleźć mojego pliku z uruchomionym Pythonem 3 w systemie Windows. Więc dodałem. przed / i wszystko działało dobrze:

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')
Ângelo Polotto
źródło
Lepiej:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
Próbowałem tego w systemie operacyjnym Windows, ale nie udało mi się.
Ângelo Polotto
Ciekawe - czy możesz wydrukować script_dir? Następnie włącz ścieżkę bezwzględną, jak wscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
Spróbuję, jeśli mi się uda, zmienię odpowiedź.
Â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

Wyjaśnienie:

Biblioteka importu:

import os

Służy __file__do uzyskania ścieżki do aktualnego skryptu:

script_path = os.path.abspath(__file__)

Oddziela ścieżkę skryptu na wiele elementów:

path_list = script_path.split(os.sep)

Usuń ostatnią pozycję z listy (rzeczywisty plik skryptu):

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

Dodaj ścieżkę do pliku względnego:

rel_path = "main/2091/data.txt

Połącz elementy listy i dodaj plik ścieżki względnej:

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

Teraz możesz zrobić, co chcesz z plikiem, na przykład:

file = open(path)
Patriots299
źródło
Zamiast tego path = "/".join(script_directory) + "/" + rel_pathpowinieneś użyć modułu os jak w path = os.path.join(script_directory, rel_path). Zamiast ręcznie analizować ścieżkę, której powinieneś używaćscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
3

Jeśli plik znajduje się w folderze nadrzędnym, np. follower.txt, możesz po prostu użyćopen('../follower.txt', 'r').read()

Olivia Liao
źródło
3

Spróbuj tego:

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 wprowadził nową standardową bibliotekę do obsługi plików i ścieżek o nazwie pathlib. Mi to pasuje!

dcampos
źródło
2

Nie jestem pewien, czy to działa wszędzie.

Używam ipythona w Ubuntu.

Jeśli chcesz odczytać plik w podkatalogu bieżącego folderu:

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

twój skrypt znajduje się w bieżącym folderze, po prostu spróbuj tego:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)
Survi
źródło
1

Python po prostu przekazuje podaną nazwę pliku do systemu operacyjnego, który go otwiera. Jeśli twój system operacyjny obsługuje ścieżki względne, takie jak main/2091/data.txt(wskazówka: tak), to zadziała.

Może się okazać, że najłatwiejszym sposobem odpowiedzi na takie pytanie jest wypróbowanie go i zobaczenie, co się stanie.

kindall
źródło
2
Nieprawda ... katalog roboczy wewnątrz skryptu to lokalizacja, z której został uruchomiony skrypt, a nie lokalizacja skryptu. Jeśli uruchomisz skrypt z innego miejsca (być może skrypt znajduje się w Twojej ścieżce systemowej), ścieżka względna do podkatalogu nie będzie działać. Proszę zobaczyć moją odpowiedź, jak to obejść.
Russ
@Russ - przykład PO używa getcwd(). Oryginalny opis przeczytałem jako „w stosunku do miejsca, w którym uruchamiam skrypt, niezależnie od tego, gdzie znajduje się kod”.
orip
@orip - OP dodał wywołanie getcwd () 3 godziny po pytaniu. Nieważne ... idź dalej. :)
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
źródło
0

Kiedy byłem początkującym, uważałem te opisy za nieco onieśmielające. Jak na początku spróbuję For Windows

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

a to podniosłoby syntax error. Często byłem zdezorientowany. Potem po pewnym surfowaniu po Google. znaleźć przyczynę wystąpienia błędu. Piszę to dla początkujących

Dzieje się tak, ponieważ w celu odczytania ścieżki w Unicode po prostu dodajesz \podczas rozpoczynania ścieżki pliku

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

A teraz działa po prostu dodaj \przed uruchomieniem katalogu.

Chidhvilas
źródło
1
Ukośniki odwrotne to znaki ucieczki dla kilku znaków. Jeśli zdarzy się, że napotkasz \tnp. \top\directory„\ T” jest interpretowane jako znak tabulacji, a twoja „sztuczka” kończy się niepowodzeniem. Najlepszą opcją jest użycie nieprzetworzonego formatu łańcucha, r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'który nie próbuje używać znaków „ucieczki”.
Ronald