Abrir arquivo em um local relativo em Python

132

Suponha que o código python seja executado não conhecido pelo diretório anterior do Windows, digamos 'main', e onde quer que o código seja instalado quando for executado, ele deverá acessar o diretório 'main / 2091 / data.txt'.

como devo usar a função aberta (local)? qual deve ser a localização?

Editar:

Eu descobri que o código simples abaixo funcionará .. ele tem alguma desvantagem?

    file="\2091\sample.txt"
    path=os.getcwd()+file
    fp=open(path,'r+');
Camélia
fonte
1
Você está usando barras invertidas sem escape. Essa é uma desvantagem.
orip 23/08/11
6
Várias desvantagens. 1) Conforme @orip, use barras para caminhos, mesmo nas janelas. Sua string não funcionará. Ou use strings cruas como r"\2091\sample.txt". Ou escapar deles como "\\2091\\sample.txt"(mas isso é irritante). Além disso, 2) você está usando getcwd (), que é o caminho em que você estava quando executou o script. Eu pensei que você queria em relação à localização do script (mas agora estou me perguntando). E 3), sempre use os.pathfunções para manipular caminhos. Sua linha de junção do caminho deve ser os.path.join(os.getcwd(), file)4) a; é inútil
Russ
3
E para uma boa medida ... 5) guardas contexto de uso para mantê-lo limpo e evitar esquecer de fechar o arquivo: with open(path, 'r+') as fp:. Veja aqui a melhor explicação das withdeclarações que já vi.
Russ
além dos cuidados necessários nas barras, como indicado, há a função os.path.abspathde obter facilmente o caminho completo do caminho relativo a ser aberto. declaração final é assim:os.path.abspath('./2091/sample.txt')
OPMendeavor

Respostas:

189

Com esse tipo de coisa, você precisa ter cuidado com o diretório atual de trabalho. Por exemplo, você não pode executar o script no diretório em que o arquivo está. Nesse caso, você não pode simplesmente usar um caminho relativo sozinho.

Se você tiver certeza de que o arquivo que você deseja está em um subdiretório abaixo de onde o script está realmente localizado, use-o __file__para ajudá-lo aqui. __file__é o caminho completo para o local em que o script que você está executando.

Então você pode mexer com algo assim:

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
fonte
Eu descobri que o código simples abaixo funcionará .. ele tem alguma desvantagem? <pre> file = "\ sample.txt" path = os.getcwd () + str (loc) + file fp = open (path, 'r +'); <code>
@Arash A desvantagem disso é que o cwd (diretório de trabalho atual) pode ser qualquer coisa e não será necessariamente onde o seu script está localizado.
Cory Mawhorter
5
__file__é um caminho relativo (pelo menos na minha configuração, por algum motivo), e você precisa ligar os.path.abspath(__file__)primeiro. osx / homebrew 2.7
Cory Mawhorter
2
os.path.dirname ( arquivo ) não está funcionando para mim no Python 2.7. Está mostrandoNameError: name '__file__' is not defined
Soumendra
1
@Soumendra Acho que você está tentando no console. Experimente em um arquivo * .py.
Enku 12/12
35

Este código funciona bem:

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
fonte
Para mim, acessar o arquivo na pasta pai da pasta atual não funcionou .. o .. é adicionado como uma string .. #
M. Paul Paul
Não funcionou no Windows. O caminho para o arquivo está correto, mas o Python afirma "arquivo não encontrado" e mostra o caminho com \\ separadores.
24519 lonstar
26

Criei uma conta para esclarecer uma discrepância que acho que encontrei na resposta original de Russ.

Para referência, sua resposta original foi:

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

Essa é uma ótima resposta, pois está tentando criar dinamicamente um caminho absoluto do sistema para o arquivo desejado.

Cory Mawhorter notou que esse __file__é um caminho relativo (também está no meu sistema) e sugeriu o uso os.path.abspath(__file__). os.path.abspath, no entanto, retorna o caminho absoluto do seu script atual (ou seja /path/to/dir/foobar.py)

Para usar este método (e como eu finalmente o fiz funcionar), você deve remover o nome do script do final do caminho:

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)

O caminho abs_file_path resultante (neste exemplo) se torna: /path/to/dir/2091/data.txt

Grant Hulegaard
fonte
14
Você pode até combinar as duas abordagens para o mais simplesos.path.dirname(os.path.abspath(__file__))
Luke Taylor
1
@LukeTaylor De fato, seria melhor do que tentar replicar a os.path.dirnamefuncionalidade você mesmo, como fiz na minha resposta no ano passado.
Grant Hulegaard
19

Depende do sistema operacional que você está usando. Se você deseja uma solução compatível com Windows e * nix, algo como:

from os import path

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

deve funcionar bem.

O pathmódulo pode formatar um caminho para qualquer sistema operacional em que esteja sendo executado. Além disso, o python lida com caminhos relativos muito bem, desde que você tenha permissões corretas.

Editar :

Como mencionado por kindall nos comentários, o python pode converter de qualquer maneira entre caminhos no estilo unix e no estilo windows, portanto um código mais simples funcionará:

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

Dito isto, o pathmódulo ainda possui algumas funções úteis.

Wilduck
fonte
3
relpath()converte um nome de caminho em um caminho relativo. Como já é um caminho relativo, não fará nada.
Kindall
Ele o converterá de um caminho no estilo unix para o caminho no estilo do Windows, se apropriado. Existe outra função no os.pathmódulo que seria uma escolha melhor?
Wilduck 23/08
1
O Windows já funcionará bem com um caminho no estilo UNIX. Pelo menos a série baseada em NT (2000, XP, Vista, 7). Nenhuma conversão é necessária.
Kindall
7
Essa resposta não está correta e causará problemas. Os caminhos relativos são, por padrão, relativos ao diretório de trabalho atual (caminho a partir do qual o script foi executado) e NÃO o local real do script. Você precisa usar __file__. Por favor, veja minha resposta.
Russ
O autor desta resposta confundiu os.path.relpath com os.path.abspath?
foobarbecue
15

Gasto muito tempo para descobrir por que meu código não conseguiu encontrar meu arquivo executando o Python 3 no sistema Windows. Então eu adicionei. antes / e tudo funcionou bem:

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
fonte
Melhor:file_path = os.path.join(script_dir, 'output03.txt')
Mr_and_Mrs_D
Eu tentei isso no sistema operacional Windows, mas não tive sucesso.
Ângelo Polotto
Interessante - você pode imprimir script_dir? Em seguida, coloque-o no caminho absoluto como emscript_dir = os.path.abspath(os.path.dirname(__file__))
Mr_and_Mrs_D
Vou tentar que, se eu conseguir, vou mudar a resposta.
Ângelo Polotto
6

Código:

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

Explicação:

Biblioteca de importação:

import os

Use __file__para atingir o caminho do script atual:

script_path = os.path.abspath(__file__)

Separa o caminho do script em vários itens:

path_list = script_path.split(os.sep)

Remova o último item da lista (o arquivo de script real):

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

Adicione o caminho do arquivo relativo:

rel_path = "main/2091/data.txt

Junte-se aos itens da lista e adicione o arquivo do caminho relativo:

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

Agora você está pronto para fazer o que quiser com o arquivo, como, por exemplo:

file = open(path)
Patriots299
fonte
Em vez de path = "/".join(script_directory) + "/" + rel_pathvocê deve usar o módulo OS como em path = os.path.join(script_directory, rel_path). Em vez de analisar manualmente o caminho que você deve usarscript_path = os.path.dirname(__file__)
Mr_and_Mrs_D
3

Se o arquivo estiver na sua pasta pai, por exemplo. follower.txt, você pode simplesmente usaropen('../follower.txt', 'r').read()

Olivia Liao
fonte
3

Tente o seguinte:

from pathlib import Path

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

f = open(file_to_open)

print(f.read())

O Python 3.4 introduziu uma nova biblioteca padrão para lidar com arquivos e caminhos chamados pathlib. Funciona para mim!

dcampos
fonte
2

Não tenho certeza se isso funciona em qualquer lugar.

Estou usando o ipython no ubuntu.

Se você quiser ler o arquivo no subdiretório da pasta atual:

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

seu script está na pasta atual, simplesmente tente o seguinte:

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

Python apenas passa o nome do arquivo que você atribui ao sistema operacional, que o abre. Se o seu sistema operacional suportar caminhos relativos como main/2091/data.txt(dica: sim), isso funcionará bem.

Você pode achar que a maneira mais fácil de responder a uma pergunta como essa é experimentá-la e ver o que acontece.

kindall
fonte
2
Não é verdade ... o diretório de trabalho dentro de um script é o local do qual você executou o script, não o local do script. Se você executar o script de outro lugar (talvez o script esteja no caminho do sistema), o caminho relativo para o subdiretório não funcionará. Por favor, veja minha resposta sobre como contornar isso.
23411 Russ
@Russ - o exemplo do OP usa getcwd(). Eu li a descrição original como "relativa ao local onde executo o script, independentemente de onde o código fica".
orip
@orip - o OP adicionou a chamada getcwd () três horas após a pergunta. Não importa ... seguir em frente. :)
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
fonte
0

Quando eu era iniciante, achei essas descrições um pouco intimidantes. Como no começo eu tentaria For Windows

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

e isso aumentaria um syntax error. Eu costumava ficar muito confuso. Depois de navegar no google. descobriu por que o erro ocorreu. Escrevendo isso para iniciantes

É porque para o caminho ser lido em Unicode, você simplesmente adiciona um \ao iniciar o caminho do arquivo

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

E agora funciona, basta adicionar \antes de iniciar o diretório.

Chidhvilas
fonte
1
As barras invertidas são caracteres de escape para vários caracteres. Se você encontrar \tcomo por exemplo \top\directory, '\ t' é interpretado como um caractere de tabulação e seu 'truque' falha. A melhor opção é usar o formato de sequência bruta r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'que não tenta 'escapar' dos caracteres.
Ronald