Apri il file in una posizione relativa in Python


133

Supponiamo che il codice python sia eseguito in modo non noto dalla precedente directory di Windows che dice 'main', e ovunque il codice sia installato durante l'esecuzione deve accedere alla directory 'main / 2091 / data.txt'.

come dovrei usare la funzione open (location)? quale dovrebbe essere la posizione?

Modificare :

Ho scoperto che sotto il semplice codice funzionerà..ha qualche svantaggio?

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

1
Stai usando barre rovesciate senza caratteri di escape. Questo è uno svantaggio.
orip,

6
Svantaggi. 1) Come per @orip, utilizzare le barre in avanti per i percorsi, anche su Windows. La tua stringa non funzionerà. O usa stringhe grezze come r"\2091\sample.txt". O sfuggirli come "\\2091\\sample.txt"(ma questo è fastidioso). Inoltre, 2) stai usando getcwd () che è il percorso in cui ti trovavi quando hai eseguito lo script. Pensavo volessi relativamente alla posizione dello script (ma ora mi chiedo). E 3), usa sempre le os.pathfunzioni per manipolare i percorsi. Il percorso della linea di giunzione dovrebbe essere os.path.join(os.getcwd(), file)4) il; è inutile
Russ,

3
E per buona misura ... 5) guardie uso di contesto per tenerlo pulito ed evitare di dimenticare di chiudere il file: with open(path, 'r+') as fp:. Vedi qui per la migliore spiegazione delle withdichiarazioni che ho visto.
Russ,

oltre alle cure necessarie sulle barre, come appena indicato, c'è la funzione os.path.abspathdi ottenere facilmente l'intero percorso del relativo percorso da aprire. la dichiarazione finale è simile alla seguente:os.path.abspath('./2091/sample.txt')
OPMendeavour

Risposte:


189

Con questo tipo di cose devi stare attento a quale sia la tua vera directory di lavoro. Ad esempio, non è possibile eseguire lo script dalla directory in cui si trova il file. In questo caso, non è possibile utilizzare un percorso relativo da solo.

Se sei sicuro che il file desiderato sia in una sottodirectory sotto la posizione dello script, puoi usarlo __file__per aiutarti. __file__è il percorso completo in cui si trova lo script in esecuzione.

Quindi puoi giocherellare con qualcosa del genere:

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)

Ho scoperto che sotto il semplice codice funzionerà..ha qualche svantaggio? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>

@Arash Lo svantaggio è che la cwd (directory di lavoro corrente) può essere qualsiasi cosa e non sarà necessariamente dove si trova il tuo script.
Cory Mawhorter,

5
__file__è un percorso relativo (almeno sulla mia configurazione, per qualche motivo), e devi os.path.abspath(__file__)prima chiamare . osx / homebrew 2.7
Cory Mawhorter,

2
os.path.dirname ( file ) non funziona per me in Python 2.7. Sta mostrandoNameError: name '__file__' is not defined
Soumendra il

1
@Soumendra Penso che tu lo stia provando nella console. Provalo in un file * .py.
Enku,

35

Questo codice funziona bene:

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)

Per me l'accesso al file nella cartella principale della cartella corrente non ha funzionato..il .. viene aggiunto come stringa ..
M. Paul

Non ha funzionato su Windows. Il percorso del file è corretto ma Python indica "file non trovato" e mostra il percorso con \\ separatori.
Lonstar,

26

Ho creato un account solo per chiarire una discrepanza che penso di aver trovato nella risposta originale di Russ.

Per riferimento, la sua risposta originale era:

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

Questa è un'ottima risposta perché sta cercando di creare dinamicamente un percorso di sistema assoluto per il file desiderato.

Cory Mawhorter ha notato che __file__è un percorso relativo (anche sul mio sistema) e ha suggerito di utilizzarlo os.path.abspath(__file__). os.path.abspath, tuttavia, restituisce il percorso assoluto del tuo script corrente (cioè /path/to/dir/foobar.py)

Per usare questo metodo (e come alla fine ho funzionato) devi rimuovere il nome dello script dalla fine del percorso:

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)

Il percorso abs_file_ risultante (in questo esempio) diventa: /path/to/dir/2091/data.txt


14
Potresti anche combinare entrambi gli approcci per il più sempliceos.path.dirname(os.path.abspath(__file__))
Luke Taylor il

1
@LukeTaylor In effetti sarebbe meglio che provare a replicare da os.path.dirnamesoli la funzionalità come ho fatto nella mia risposta l'anno scorso.
Grant Hulegaard,

19

Dipende dal sistema operativo in uso. Se vuoi una soluzione compatibile con Windows e * nix qualcosa del genere:

from os import path

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

dovrebbe funzionare bene.

Il pathmodulo è in grado di formattare un percorso per qualsiasi sistema operativo su cui è in esecuzione. Inoltre, Python gestisce bene i percorsi relativi, purché si disponga delle autorizzazioni corrette.

Modifica :

Come menzionato da kindall nei commenti, Python può comunque convertire tra percorsi in stile unix e percorsi in stile windows, quindi funzionerà anche un codice più semplice:

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

Detto questo, il pathmodulo ha ancora alcune funzioni utili.


3
relpath()converte un percorso in un percorso relativo. Dal momento che è già un percorso relativo, non farà nulla.
kindall

Se necessario, lo convertirà da un percorso in stile unix in un percorso in stile Windows. C'è un'altra funzione nel os.pathmodulo che sarebbe una scelta migliore?
Wilduck,

1
Windows funzionerà già bene con un percorso in stile UNIX. Almeno la serie basata su NT sarà (2000, XP, Vista, 7). Nessuna conversione è necessaria.
kindall

7
Questa risposta non è del tutto corretta e causerà problemi. I percorsi relativi sono per impostazione predefinita relativi alla directory di lavoro corrente (percorso da cui è stato eseguito lo script) e NON alla posizione effettiva dello script. È necessario utilizzare __file__. Si prega di vedere la mia risposta.
Russ,

L'autore di questa risposta ha confuso os.path.relpath con os.path.abspath?
foobaremade

15

Passo molto tempo a scoprire perché il mio codice non è riuscito a trovare il mio file che esegue Python 3 sul sistema Windows. Quindi ho aggiunto. prima / e tutto ha funzionato bene:

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

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

Ho provato sul sistema operativo Windows, ma non ho avuto successo.
Angelo Polotto,

Interessante: puoi stampare script_dir? Quindi giralo sul percorso assoluto come inscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D

Proverò che, se ci riuscirò, cambierò la risposta.
Angelo Polotto,

6

Codice:

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

Spiegazione:

Libreria di importazione:

import os

Utilizzare __file__per raggiungere il percorso dello script corrente:

script_path = os.path.abspath(__file__)

Separa il percorso dello script in più elementi:

path_list = script_path.split(os.sep)

Rimuovi l'ultimo elemento nell'elenco (il file di script effettivo):

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

Aggiungi il percorso del file relativo:

rel_path = "main/2091/data.txt

Unisci le voci dell'elenco e aggiungi il relativo file del percorso:

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

Ora sei pronto per fare quello che vuoi con il file, come ad esempio:

file = open(path)

Invece di path = "/".join(script_directory) + "/" + rel_pathte dovresti usare il modulo os come in path = os.path.join(script_directory, rel_path). Invece di analizzare manualmente il percorso che dovresti usarescript_path = os.path.dirname(__file__)
Mr_and_Mrs_D

4

Prova questo:

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 ha introdotto una nuova libreria standard per la gestione di file e percorsi denominata pathlib. Per me funziona!


3

Se il file si trova nella cartella principale, ad es. follower.txt, puoi semplicemente usareopen('../follower.txt', 'r').read()


2

Non sono sicuro se questo funziona ovunque.

Sto usando ipython in Ubuntu.

Se vuoi leggere il file nella sottodirectory della cartella corrente:

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

lo script è nella cartella corrente, prova semplicemente questo:

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

1

Python passa semplicemente il nome file che lo dai al sistema operativo, che lo apre. Se il tuo sistema operativo supporta percorsi relativi come main/2091/data.txt(suggerimento: funziona), allora funzionerà bene.

Potresti scoprire che il modo più semplice per rispondere a una domanda come questa è provarla e vedere cosa succede.


2
Non vero ... la directory di lavoro all'interno di uno script è la posizione da cui è stato eseguito lo script, non la posizione dello script. Se esegui lo script altrove (forse lo script si trova nel tuo percorso di sistema) il percorso relativo alla sottodirectory non funzionerà. Si prega di vedere la mia risposta su come aggirare questo.
Russ,

@Russ - utilizza l'esempio del PO getcwd(). Ho letto la descrizione originale come "relativa a dove eseguo lo script, indipendentemente da dove si trova il codice".
Orip,

@orip: l'OP ha aggiunto la chiamata getcwd () 3 ore dopo la domanda. Non importa ... andare avanti. :)
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

Quando ero un principiante ho trovato queste descrizioni un po 'intimidatorie. Come prima ci proverei For Windows

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

e questo solleverebbe un syntax error. Ho usato molto confuso. Quindi dopo aver navigato su Google. trovato il motivo per cui si è verificato l'errore. Scrivere questo per i principianti

È perché per il percorso da leggere in Unicode è sufficiente aggiungere un \all'avvio del percorso del file

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

E ora funziona basta aggiungere \prima di avviare la directory.


1
Le barre rovesciate sono caratteri di escape per diversi personaggi. Se ti capita di incontrare, \tad esempio \top\directory, "\ t" viene interpretato come un carattere di tabulazione e il tuo "trucco" fallisce. L'opzione migliore è utilizzare il formato stringa non elaborato r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'che non tenta di "sfuggire" ai caratteri.
Ronald
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.