Eu costumava abrir arquivos que estavam no mesmo diretório do script Python em execução no momento, simplesmente usando um comando como
open("Some file.txt", "r")
No entanto, descobri que, quando o script era executado no Windows, clicando duas vezes nele, tentava abrir o arquivo do diretório errado.
Desde então, eu usei um comando do formulário
open(os.path.join(sys.path[0], "Some file.txt"), "r")
sempre que eu queria abrir um arquivo. Isso funciona para meu uso específico, mas não tenho certeza se sys.path[0]
pode falhar em outro caso de uso.
Portanto, minha pergunta é: Qual é a melhor e mais confiável maneira de abrir um arquivo que está no mesmo diretório do script Python em execução no momento?
Aqui está o que eu consegui descobrir até agora:
os.getcwd()
eos.path.abspath('')
retorne o "diretório de trabalho atual", não o diretório de scripts.os.path.dirname(sys.argv[0])
eos.path.dirname(__file__)
retorne o caminho usado para chamar o script, que pode ser relativo ou mesmo em branco (se o script estiver no cwd). Além disso,__file__
não existe quando o script é executado no IDLE ou no PythonWin.sys.path[0]
eos.path.abspath(os.path.dirname(sys.argv[0]))
parece retornar o diretório de scripts. Não tenho certeza se há alguma diferença entre esses dois.
Editar:
Acabei de perceber que o que eu quero fazer seria melhor descrito como "abra um arquivo no mesmo diretório que o módulo que o contém". Em outras palavras, se eu importar um módulo que escrevi que esteja em outro diretório e esse módulo abrir um arquivo, quero que ele procure o arquivo no diretório do módulo. Acho que nada que eu encontrei é capaz de fazer isso ...
__file__
não puder ser usado, use emsys.argv[0]
vez dedirname(__file__)
. O resto deve funcionar como esperado. Eu gosto de usar__file__
porque no código da biblioteca,sys.argv[0]
talvez não aponte para o seu código, especialmente se importado por algum script de terceiros.realpath( join( getcwd(), dirname(__file__) ))
como descrito aqui?Para citar a documentação do Python:
sys.path [0] é o que você está procurando.
fonte
os.path.join(sys.path[0], 'some file.txt')
. Isso deve lidar com espaços e barras corretamente em todos os sistemas.Ok, aqui está o que eu faço
sys.argv é sempre o que você digita no terminal ou usa como caminho de arquivo ao executá-lo com python.exe ou pythonw.exe
Por exemplo, você pode executar o arquivo text.py de várias maneiras, cada uma com uma resposta diferente, sempre com o caminho que o python foi digitado.
Ok, então saiba que você pode obter o nome do arquivo, grande coisa. Agora, para obter o diretório do aplicativo, você pode usar o os.path, especificamente abspath e dirname
Isso produzirá o seguinte:
ele sempre produzirá isso, não importa se você digita python test.py ou python "C: \ Documents and Settings \ Admin \ test.py"
O problema de usar __file__ Considere estes dois arquivos test.py
import_test.py
Saída de "python test.py"
Saída de "python test_import.py"
Então, como você pode ver, o arquivo fornece sempre o arquivo python do qual está sendo executado, enquanto sys.argv [0] fornece o arquivo que você executou sempre do intérprete. Dependendo das suas necessidades, você precisará escolher qual melhor se adequa às suas necessidades.
fonte
__file__
é suposto que "sempre dar-lhe o caminho para o arquivo atual", esys.argv[0]
é suposto que "sempre dar o caminho do script que iniciou o processo". De qualquer forma, o uso__file__
do script invocado sempre fornece resultados precisos.__file__
no nível superior do script, ele funcionará conforme o esperado.Consegui usar o código fornecido pelo dcolish com êxito, pois estava tendo um problema semelhante ao ler um arquivo de texto específico. O arquivo não está no mesmo código que o arquivo Python.
fonte
Eu faria assim:
O código acima cria um caminho absoluto para o arquivo usando abspath e é equivalente a usar
normpath(join(os.getcwd(), path))
[isso é dos pydocs]. Em seguida, ele verifica se esse arquivo realmente existe e, em seguida, usa um gerenciador de contexto para abri-lo, para que você não precise se lembrar de fechar o identificador de arquivo. IMHO, fazê-lo dessa maneira, poupará muita dor a longo prazo.fonte
os.path.abspath
não resolve caminhos para arquivos na mesma pasta que o script se o script não estiver no diretório atual.