Saya menjalankan shell python dari crontab setiap menit:
* * * * * /home/udi/foo/bar.py
/home/udi/foo
memiliki beberapa subdirektori yang diperlukan, seperti /home/udi/foo/log
dan /home/udi/foo/config
, yang /home/udi/foo/bar.py
merujuk pada.
Masalahnya adalah crontab
menjalankan skrip dari direktori kerja yang berbeda, jadi mencoba membuka ./log/bar.log
gagal.
Apakah ada cara yang bagus untuk memberitahu skrip untuk mengubah direktori kerja ke direktori skrip sendiri? Saya lebih suka solusi yang akan bekerja untuk lokasi skrip apa pun, daripada secara eksplisit memberitahu skrip di mana skrip itu berada.
EDIT:
os.chdir(os.path.dirname(sys.argv[0]))
Merupakan solusi elegan paling kompak. Terima kasih atas jawaban dan penjelasan Anda!
python
working-directory
Adam Matan
sumber
sumber
crontab
use-case: keduanyasys.argv[0]
dan__file__
gagal jika skrip dijalankan menggunakanexecfile()
;inspect
solusi berbasis bisa digunakan sebagai gantinya.Jawaban:
Ini akan mengubah direktori kerja Anda saat ini sehingga membuka jalur relatif akan berfungsi:
Namun, Anda bertanya bagaimana cara mengubah ke direktori apa pun skrip Python Anda berada, bahkan jika Anda tidak tahu direktori apa yang akan terjadi ketika Anda sedang menulis skrip Anda. Untuk melakukan ini, Anda dapat menggunakan
os.path
fungsi:Ini mengambil nama file skrip Anda, mengonversinya menjadi jalur absolut, lalu mengekstrak direktori jalur itu, lalu berubah ke direktori itu.
sumber
__file__
sebagai gantisys.argv[0]
.os.chdir(os.path.dirname(__file__))
?__file__
gagal dalam program "beku" (dibuat menggunakan py2exe, PyInstaller, cx_Freeze).sys.argv[0]
bekerja. @ChrisDown: Jika Anda ingin mengikuti symlinks;os.path.realpath()
bisa digunakan.__file__
belum menjadi path absolut, dan pengguna telah mengubah direktori yang berfungsi, makaos.path.abspath
akan tetap gagal.Anda bisa mendapatkan versi yang lebih pendek dengan menggunakan
sys.path[0]
.Dari http://docs.python.org/library/sys.html#sys.path
sumber
Jangan lakukan ini.
Skrip dan data Anda tidak boleh dihaluskan menjadi satu direktori besar. Menaruh kode Anda di beberapa lokasi yang diketahui (
site-packages
atau/var/opt/udi
atau sesuatu) terpisah dari data Anda. Gunakan kontrol versi yang baik pada kode Anda untuk memastikan bahwa Anda memiliki versi saat ini dan sebelumnya terpisah satu sama lain sehingga Anda dapat kembali ke versi sebelumnya dan menguji versi yang akan datang.Intinya: Jangan menyatukan kode dan data.
Data sangat berharga. Kode datang dan pergi.
Berikan direktori yang berfungsi sebagai nilai argumen baris perintah. Anda dapat memberikan default sebagai variabel lingkungan. Jangan menyimpulkannya (atau menebaknya)
Jadikan nilai argumen yang diperlukan dan lakukan ini.
Jangan "menganggap" direktori berdasarkan lokasi perangkat lunak Anda. Ini tidak akan berhasil dengan baik dalam jangka panjang.
sumber
Ubah perintah crontab Anda ke
The
(...)
dimulai sub-shell yang mengeksekusi crond Anda sebagai satu perintah. The|| exit 1
menyebabkan cronjob Anda gagal dalam hal ini direktori tidak tersedia.Meskipun solusi lain mungkin lebih elegan dalam jangka panjang untuk skrip spesifik Anda, contoh saya masih bisa berguna dalam kasus di mana Anda tidak dapat memodifikasi program atau perintah yang ingin Anda jalankan.
sumber
|| exit 1
. Sangat menyegarkan melihat ini. Meskipun saya harus bertanya-tanya mengapa Anda tidak melakukannyacd /home/udi/foo/ && ./bar.py
exit 1
crond Anda akan diberi tahu tentang kesalahan, dan dalam kebanyakan kasus akan mengirim pemberitahuan email tentang kegagalan tersebut.