Qual é a maneira mais elegante de verificar se o diretório em que um arquivo será gravado existe e, se não, criar o diretório usando Python? Aqui está o que eu tentei:
import os
file_path = "/my/directory/filename.txt"
directory = os.path.dirname(file_path)
try:
os.stat(directory)
except:
os.mkdir(directory)
f = file(filename)
De alguma forma, eu perdi os.path.exists
(obrigado kanja, Blair e Douglas). Isto é o que eu tenho agora:
def ensure_dir(file_path):
directory = os.path.dirname(file_path)
if not os.path.exists(directory):
os.makedirs(directory)
Existe uma bandeira para "aberto", que faz isso acontecer automaticamente?
os.path.mkdir
não existe. Éos.mkdir
.p
, aqui está o meu trecho de código:os.makedirs(p[:p.rindex(os.path.sep)], exist_ok=True)
Respostas:
No Python ≥ 3.5, use
pathlib.Path.mkdir
:Para versões mais antigas do Python, vejo duas respostas com boas qualidades, cada uma com uma pequena falha, por isso vou dar a minha opinião:
Tente
os.path.exists
e considereos.makedirs
a criação.Conforme observado nos comentários e em outros lugares, há uma condição de corrida - se o diretório for criado entre
os.path.exists
asos.makedirs
chamadas e as chamadas, aos.makedirs
falha será com umOSError
. Infelizmente, a capturaOSError
e a continuação de mantas não são infalíveis, pois ignoram a falha na criação do diretório devido a outros fatores, como permissões insuficientes, disco cheio, etc.Uma opção seria interceptar
OSError
e examinar o código de erro incorporado (consulte Existe uma maneira de obter várias plataformas de obter informações do OSError do Python ):Como alternativa, pode haver um segundo
os.path.exists
, mas suponha que outro criou o diretório após a primeira verificação e o removeu antes da segunda - ainda poderíamos ser enganados.Dependendo do aplicativo, o perigo de operações simultâneas pode ser mais ou menos do que o perigo causado por outros fatores, como permissões de arquivo. O desenvolvedor precisaria saber mais sobre o aplicativo específico que está sendo desenvolvido e seu ambiente esperado antes de escolher uma implementação.
As versões modernas do Python aprimoram bastante esse código, expondo
FileExistsError
(no 3.3 +) ...... e permitindo que um argumento de palavra-chave seja
os.makedirs
chamadoexist_ok
(em 3.2+).fonte
os.path.exists
também retornaTrue
para um arquivo. Eu postei uma resposta para resolver isso.exists_ok
parâmetro aos.makedirs()
pode ser usado para cobrir como a existência anterior do caminho é tratada, desde o Python 3.2.os.mkdirs()
pode criar pastas indesejadas se um separador de caminhos for acidentalmente deixado de fora, a pasta atual não for como o esperado, um elemento de caminho conterá o separador de caminhos. Se você usaros.mkdir()
esses erros, haverá uma exceção, alertando você sobre a existência deles.Python 3.5 ou superior:
pathlib.Path.mkdir
conforme usado acima, recursivamente cria o diretório e não gera uma exceção se o diretório já existir. Se você não precisa ou deseja que os pais sejam criados, pule oparents
argumento.Python 3.2 ou superior:
Usando
pathlib
:Se puder, instale o
pathlib
backport atual nomeadopathlib2
. Não instale o backport não mantido mais antigo chamadopathlib
. Em seguida, consulte a seção Python 3.5+ acima e use-a da mesma forma.Se você estiver usando o Python 3.4, mesmo que o acompanhe
pathlib
, está faltando aexist_ok
opção útil . O backport destina-se a oferecer uma implementação mais nova e superior,mkdir
que inclui essa opção ausente.Usando
os
:os.makedirs
conforme usado acima, recursivamente cria o diretório e não gera uma exceção se o diretório já existir. Ele possui oexist_ok
argumento opcional apenas se você estiver usando o Python 3.2+, com um valor padrão deFalse
. Este argumento não existe no Python 2.x até 2.7. Como tal, não há necessidade de manipulação manual de exceções, como no Python 2.7.Python 2.7+:
Usando
pathlib
:Se puder, instale o
pathlib
backport atual nomeadopathlib2
. Não instale o backport não mantido mais antigo chamadopathlib
. Em seguida, consulte a seção Python 3.5+ acima e use-a da mesma forma.Usando
os
:Embora uma solução ingênua possa ser usada primeiro
os.path.isdir
seguida poros.makedirs
, a solução acima reverte a ordem das duas operações. Ao fazer isso, evita que uma condição de corrida comum tenha a ver com uma tentativa duplicada de criar o diretório e também desambigua arquivos dos diretórios.Observe que capturar a exceção e usar
errno
é de utilidade limitada porqueOSError: [Errno 17] File exists
, ou sejaerrno.EEXIST
, é gerado para arquivos e diretórios. É mais confiável simplesmente verificar se o diretório existe.Alternativa:
mkpath
cria o diretório aninhado e não faz nada se o diretório já existir. Isso funciona no Python 2 e 3.De acordo com o Bug 10948 , uma limitação grave dessa alternativa é que ela funciona apenas uma vez por processo python para um determinado caminho. Em outras palavras, se você usá-lo para criar um diretório, exclua o diretório de dentro ou fora do Python, use
mkpath
novamente para recriar o mesmo diretório,mkpath
simplesmente usará silenciosamente suas informações em cache inválidas de ter criado o diretório anteriormente e não o fará. faça o diretório novamente. Por outro lado,os.makedirs
não depende desse cache. Essa limitação pode ser boa para alguns aplicativos.No que diz respeito ao modo do diretório , consulte a documentação se você se importa.
fonte
os.path.isdir
outra pessoa excluir a pasta, você gerará o erro errado, desatualizado e confuso dessa pasta.O uso de try except e o código de erro correto do módulo errno se livra da condição de corrida e é multiplataforma:
Em outras palavras, tentamos criar os diretórios, mas se eles já existem, ignoramos o erro. Por outro lado, qualquer outro erro é relatado. Por exemplo, se você criar o diretório 'a' de antemão e remover todas as permissões dele, será
OSError
gerado umerrno.EACCES
erro com (Permissão negada, erro 13).fonte
exception.errno != errno.EEXIST
, inadvertidamente, ignorará o caso quando o caminho existir, mas for um objeto que não seja de diretório, como um arquivo. Idealmente, a exceção deve ser levantada se o caminho for um objeto que não seja de diretório.os.makedirs(path,exist_ok=True)
exist_ok
parâmetro foi introduzido no Python 3.2. Não está presente no Python 2.x. Vou incorporá-lo na minha resposta.Eu pessoalmente recomendo que você use
os.path.isdir()
para testar em vez deos.path.exists()
.Se você tem:
E uma entrada tola do usuário:
... Você terminará com um diretório nomeado
filename.etc
quando passar esse argumento paraos.makedirs()
se testaros.path.exists()
.fonte
Verifique
os.makedirs
: (Ele garante que o caminho completo exista.)Para lidar com o fato de que o diretório possa existir, pegue
OSError
. (Seexist_ok
forFalse
(o padrão), umOSError
será gerado se o diretório de destino já existir.)fonte
OSError
será gerado aqui se o caminho for um arquivo ou diretório existente. Eu postei uma resposta para resolver isso.OSError
antes de decidir ignorá-la. Consulte stackoverflow.com/a/5032238/763269 .A partir do Python 3.5,
pathlib.Path.mkdir
tem umaexist_ok
bandeira:Isso cria recursivamente o diretório e não gera uma exceção se o diretório já existir.
(assim como
os.makedirs
obteve umaexist_ok
flag a partir do python 3.2, por exemploos.makedirs(path, exist_ok=True)
)fonte
Insights sobre as especificidades desta situação
Você fornece um arquivo específico em um determinado caminho e extrai o diretório do caminho do arquivo. Depois de verificar se você possui o diretório, tente abrir um arquivo para leitura. Para comentar sobre este código:
Queremos evitar a substituição da função interna
dir
,. Além disso,filepath
ou talvezfullfilepath
seja, provavelmente, um nome semântico melhor do quefilename
isso, seria melhor escrito:Seu objetivo final é abrir esse arquivo, você declara inicialmente, para escrever, mas você está essencialmente se aproximando desse objetivo (com base no seu código) assim, que abre o arquivo para leitura :
Assumindo abertura para leitura
Por que você criaria um diretório para um arquivo que espera estar lá e possa ler?
Apenas tente abrir o arquivo.
Se o diretório ou arquivo não estiver lá, você receberá um
IOError
número de erro associado:errno.ENOENT
apontará para o número de erro correto, independentemente da sua plataforma. Você pode pegá-lo se quiser, por exemplo:Supondo que estamos abrindo para escrever
Provavelmente é isso que você está querendo.
Nesse caso, provavelmente não estamos enfrentando nenhuma condição de corrida. Portanto, faça como estava, mas observe que, para escrever, você precisa abrir com o
w
modo (oua
anexar). Também é uma prática recomendada do Python usar o gerenciador de contexto para abrir arquivos.No entanto, digamos que temos vários processos Python que tentam colocar todos os dados no mesmo diretório. Então, podemos ter disputas sobre a criação do diretório. Nesse caso, é melhor encerrar a
makedirs
chamada em um bloco de tentativa-exceção.fonte
Experimente a
os.path.exists
funçãofonte
os.path.mkdir()
método. O módulo os.path implementa algumas funções úteis nos nomes de caminho .Anotei o seguinte. Não é totalmente infalível.
Agora, como eu disse, isso não é realmente infalível, porque temos a possibilidade de não conseguir criar o diretório e outro processo de criação durante esse período.
fonte
os.path.exists
- consulte stackoverflow.com/a/5032238/763269 e (2) êxito ativadoos.path.exists
não significa que o diretório exista, apenas que o caminho existe existe - pode ser um arquivo, um link simbólico ou outro objeto do sistema de arquivos.A resposta direta a isso é, assumindo uma situação simples em que você não espera que outros usuários ou processos mexam com seu diretório:
ou se a criação do diretório estiver sujeita às condições de corrida (ou seja, se após a verificação do caminho existir, algo já pode ter sido feito):
Mas talvez uma abordagem ainda melhor seja evitar o problema de contenção de recursos usando diretórios temporários por meio de
tempfile
:Aqui está o essencial do documento on-line:
Novo no Python 3.5:
pathlib.Path
comexist_ok
Há um novo
Path
objeto (a partir do 3.4) com muitos métodos que você gostaria de usar com caminhos - um dos quais émkdir
.(Por contexto, estou rastreando meu representante semanal com um script. Aqui estão as partes relevantes do código do script que me permitem evitar atingir o estouro de pilha mais de uma vez por dia para os mesmos dados.)
Primeiro as importações relevantes:
Não precisamos lidar
os.path.join
agora - basta juntar as partes do caminho com um/
:Em seguida, garanto que o diretório existe de maneira independente - o
exist_ok
argumento aparece no Python 3.5:Aqui está a parte relevante da documentação :
Aqui está um pouco mais do script - no meu caso, não estou sujeito a uma condição de corrida, só tenho um processo que espera que o diretório (ou arquivos contidos) esteja lá e não tenho nada tentando remover o diretório.
Path
os objetos precisam ser coagidosstr
antes que outras APIs que esperamstr
caminhos possam usá-los.Talvez o Pandas deva ser atualizado para aceitar instâncias da classe base abstrata
os.PathLike
,.fonte
No Python 3.4, você também pode usar o novo
pathlib
módulo :fonte
pathlib
e ondepathlib2
para os novos usuários, e eu acho que prós aqui vai descobrir a depreciação;)A documentação relevante do Python sugere o uso do estilo de codificação EAFP (mais fácil pedir perdão do que permissão) . Isso significa que o código
é melhor que a alternativa
A documentação sugere isso exatamente por causa da condição de corrida discutida nesta pergunta. Além disso, como outros mencionam aqui, há uma vantagem de desempenho em consultar uma vez em vez de duas vezes o sistema operacional. Finalmente, o argumento apresentado, potencialmente, a favor do segundo código em alguns casos - quando o desenvolvedor conhece o ambiente em que o aplicativo está sendo executado - só pode ser defendido no caso especial em que o programa configurou um ambiente privado para próprio (e outras instâncias do mesmo programa).
Mesmo nesse caso, essa é uma prática ruim e pode levar à depuração inútil longa. Por exemplo, o fato de definirmos as permissões para um diretório não deve nos deixar com as permissões de impressão definidas adequadamente para nossos propósitos. Um diretório pai pode ser montado com outras permissões. Em geral, um programa deve sempre funcionar corretamente e o programador não deve esperar um ambiente específico.
fonte
No Python3 ,
os.makedirs
suporta configuraçãoexist_ok
. A configuração padrão éFalse
, o que significa que umOSError
será gerado se o diretório de destino já existir. Ao definirexist_ok
comoTrue
,OSError
(o diretório existe) será ignorado e o diretório não será criado.No Python2 ,
os.makedirs
não suporta configuraçãoexist_ok
. Você pode usar a abordagem na resposta de heikki-toivonen :fonte
Para uma solução de uma linha, você pode usar
IPython.utils.path.ensure_dir_exists()
:Na documentação : Verifique se existe um diretório. Se não existir, tente criá-lo e proteja-o contra uma condição de corrida, se outro processo estiver fazendo o mesmo.
fonte
IPython
é absolutamente garantido que o módulo esteja presente. Ele está presente nativamente no meu Mac, mas não em nenhuma das minhas instalações do Python no Linux. Basicamente, não é um dos módulos listados no Python Module Index .pip install ipython
ou incluir a dependência no seu requirements.txt ou pom.xml . Documentação: ipython.org/install.htmlVocê pode usar
mkpath
Observe que ele também criará os diretórios ancestrais.
Funciona para Python 2 e 3.
fonte
distutils.dir_util
não faz parte da API pública distutil e tem problemas em ambientes com vários threads: bugs.python.org/issue10948distutils.dir_util.mkpath
é que, se você criar um diretório, excluí-lo de dentro ou fora do Python e usá-lomkpath
novamente,mkpath
usará simplesmente suas informações em cache inválidas de ter criado o diretório anteriormente e na verdade, não crie o diretório novamente. Por outro lado,os.makedirs
não depende desse cache.Eu uso
os.path.exists()
, aqui está um script Python 3 que pode ser usado para verificar se um diretório existe, criar um se ele não existir e excluí-lo se ele existir (se desejado).Ele solicita aos usuários a entrada do diretório e pode ser facilmente modificado.
fonte
Você pode usar
os.listdir
para isso:fonte
Eu encontrei este Q / A e fiquei inicialmente intrigado com algumas das falhas e erros que estava recebendo. Estou trabalhando no Python 3 (v.3.5 em um ambiente virtual Anaconda em um sistema Arch Linux x86_64).
Considere esta estrutura de diretórios:
Aqui estão minhas experiências / notas, que esclarecem as coisas:
Conclusão: na minha opinião, o "Método 2" é mais robusto.
[1] Como posso criar um diretório se ele não existe?
[2] https://docs.python.org/3/library/os.html#os.makedirs
fonte
Eu vi as respostas de Heikki Toivonen e ABB e pensei nessa variação.
fonte
Use este comando check e create dir
fonte
Por que não usar o módulo subprocesso se estiver executando em uma máquina que suporta comando
mkdir
com-p
opção? Funciona no python 2.7 e python 3.6Deve fazer o truque na maioria dos sistemas.
Em situações em que a portabilidade não importa (por exemplo, usando o docker), a solução são 2 linhas limpas. Você também não precisa adicionar lógica para verificar se os diretórios existem ou não. Finalmente, é seguro executar novamente sem efeitos colaterais
Se você precisar de tratamento de erros:
fonte
Se você considerar o seguinte:
significa que um diretório (caminho) existe E é um diretório. Então, para mim desta maneira, faz o que eu preciso. Para garantir que ela seja uma pasta (não um arquivo) e exista.
fonte
Chame a função
create_dir()
no ponto de entrada do seu programa / projeto.fonte
Você precisa definir o caminho completo antes de criar o diretório:
Isso funciona para mim e espero que funcione para você também
fonte
Isto irá verificar se o arquivo está lá, se não estiver, então ele será criado.
fonte