Eu corro um shell python do crontab a cada minuto:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
possui alguns subdiretórios necessários, como /home/udi/foo/log
e /home/udi/foo/config
, ao qual /home/udi/foo/bar.py
se refere.
O problema é que crontab
o script é executado a partir de um diretório de trabalho diferente, portanto, a tentativa de abrir ./log/bar.log
falha.
Existe uma boa maneira de dizer ao script para alterar o diretório de trabalho para o próprio diretório do script? Gostaria de uma solução que funcionasse para qualquer local de script, em vez de dizer explicitamente onde está o script.
EDITAR:
os.chdir(os.path.dirname(sys.argv[0]))
Foi a solução elegante mais compacta. Obrigado por suas respostas e explicações!
python
working-directory
Adam Matan
fonte
fonte
crontab
caso de uso: bothsys.argv[0]
e__file__
fail se o script for executado usandoexecfile()
;inspect
solução baseada em dados poderia ser usada.Respostas:
Isso mudará seu diretório de trabalho atual para, para que a abertura de caminhos relativos funcione:
No entanto, você perguntou como mudar para qualquer diretório em que seu script Python esteja localizado, mesmo que você não saiba qual diretório será esse quando estiver escrevendo seu script. Para fazer isso, você pode usar as
os.path
funções:Isso pega o nome do arquivo do seu script, converte-o para um caminho absoluto, extrai o diretório desse caminho e depois muda para esse diretório.
fonte
__file__
vez desys.argv[0]
.os.chdir(os.path.dirname(__file__))
?__file__
falha em programas "congelados" (criados usando py2exe, PyInstaller, cx_Freeze).sys.argv[0]
trabalho. @ ChrisDown: Se você deseja seguir links simbólicos;os.path.realpath()
poderia ser usado.__file__
ainda não é um caminho absoluto e o usuário alterou o diretório de trabalho, eleos.path.abspath
falhará de qualquer maneira.Você pode obter uma versão mais curta usando
sys.path[0]
.Em http://docs.python.org/library/sys.html#sys.path
fonte
Não faça isso.
Seus scripts e seus dados não devem ser compactados em um grande diretório. Coloque seu código em algum local conhecido (
site-packages
ou/var/opt/udi
ou algo assim) separar de seus dados. Use um bom controle de versão no seu código para garantir que as versões atual e anterior sejam separadas uma da outra, para que você possa voltar às versões anteriores e testar versões futuras.Conclusão: não misture código e dados.
Dados são preciosos. O código vem e vai.
Forneça o diretório ativo como um valor do argumento da linha de comandos. Você pode fornecer um padrão como uma variável de ambiente. Não deduza (ou adivinhe)
Crie um valor de argumento necessário e faça isso.
Não "assuma" um diretório com base na localização do seu software. Não vai funcionar bem a longo prazo.
fonte
Mude seu comando crontab para
O
(...)
inicia um sub-shell que sua crond executa como um único comando. O|| exit 1
faz com que seu cronjob a falhar no caso de que o diretório não está disponível.Embora as outras soluções possam ser mais elegantes a longo prazo para seus scripts específicos, meu exemplo ainda pode ser útil nos casos em que você não pode modificar o programa ou comando que deseja executar.
fonte
|| exit 1
. É refrescante ver isso. Embora eu tenho que perguntar por que você não iria apenas fazercd /home/udi/foo/ && ./bar.py
exit 1
seu crond será notificado sobre um erro e, na maioria dos casos, enviará uma notificação por email da falha.