with - relative path open python




Caminhos Relativos em Python (8)

Agora é 2018, e o Python já evoluiu para o __future__ há muito tempo. Então, que tal usar o incrível pathlib vem com o Python 3.4 para realizar a tarefa em vez de lutar com os , os.path , glob , shutil , etc.

Então nós temos 3 caminhos aqui (possivelmente duplicados):

  • mod_path : qual é o caminho do script auxiliar simples
  • src_path : que contém alguns arquivos de modelo esperando para serem copiados.
  • cwd : diretório atual , o destino desses arquivos de modelo.

e o problema é: nós não temos o caminho completo de src_path , só sabemos que é caminho relativo para o mod_path .

Agora vamos resolver isso com o incrível pathlib :

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

No futuro, é simples assim. : D

Além disso, podemos selecionar e verificar e copiar / mover esses arquivos de modelo com o pathlib :

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)

Eu estou construindo um script auxiliar simples para o trabalho que irá copiar alguns arquivos de modelo em nossa base de código para o diretório atual. Eu não tenho, no entanto, o caminho absoluto para o diretório onde os modelos são armazenados. Eu tenho um caminho relativo do script, mas quando eu chamo o script trata isso como um caminho relativo ao diretório de trabalho atual. Existe uma maneira de especificar que esse URL relativo é o local do script?


Ao invés de usar

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

como na resposta aceita, seria mais robusto usar:

import inspect
import os
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1]))
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

porque usar __file__ retornará o arquivo do qual o módulo foi carregado, se ele foi carregado de um arquivo, portanto, se o arquivo com o script for chamado de outro lugar, o diretório retornado não estará correto.

Essas respostas fornecem mais detalhes: https://.com/a/31867043/5542253 e https://.com/a/50502/5542253


Considere meu código:

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)

Este código retornará o caminho absoluto para o script principal.

import os
def whereAmI():
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__))

Isso funcionará mesmo em um módulo.


No arquivo que tem o script, você quer fazer algo assim:

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')

Isso lhe dará o caminho absoluto para o arquivo que você está procurando. Observe que, se você estiver usando setuptools, provavelmente deverá usar sua API de recursos de pacote .

ATUALIZAÇÃO : Estou respondendo a um comentário aqui para poder colar um exemplo de código. :-)

Estou correto em pensar que __file__ não está sempre disponível (por exemplo, quando você executa o arquivo diretamente em vez de importá-lo)?

Estou assumindo que você quer dizer o script __main__ quando mencionar a execução do arquivo diretamente. Se assim for, isso não parece ser o caso no meu sistema (python 2.5.1 no OS X 10.5.7):

#foo.py
import os
print os.getcwd()
print __file__

#in the interactive interpreter
>>> import foo
/Users/jason
foo.py

#and finally, at the shell:
~ % python foo.py
/Users/jason
foo.py

No entanto, eu sei que existem algumas peculiaridades com __file__ em extensões C. Por exemplo, posso fazer isso no meu Mac:

>>> import collections #note that collections is a C extension in Python 2.5
>>> collections.__file__
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-
dynload/collections.so'

No entanto, isso gera uma exceção na minha máquina Windows.


O que funcionou para mim é usar o sys.path.insert . Então eu especifiquei o diretório que eu precisava ir. Por exemplo, eu só precisava subir um diretório.

import sys
sys.path.insert(0, '../')

Uma alternativa que funciona para mim:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))

Veja sys.path Como inicializado na inicialização do programa, o primeiro item desta lista, path [0], é o diretório que contém o script que foi usado para invocar o interpretador Python.

Use este caminho como a pasta raiz da qual você aplica seu caminho relativo

>>> import sys
>>> import os.path
>>> sys.path[0]
'C:\\Python25\\Lib\\idlelib'
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6
>>> os.path.join(sys.path[0], "path_to_libs")
'C:\\Python25\\Lib\\idlelib\\path_to_libs'




path