Saat mencoba menulis stdout dari skrip Python ke file teks ( python script.py > log
), file teks dibuat ketika perintah dimulai, tetapi konten yang sebenarnya tidak ditulis sampai skrip Python selesai. Sebagai contoh:
script.py:
import time
for i in range(10):
print('bla')
time.sleep(5)
mencetak ke stdout setiap 5 detik saat dipanggil dengan python script.py
, tetapi ketika saya menelepon python script.py > log
, ukuran file log tetap nol sampai skrip selesai. Apakah mungkin untuk langsung menulis ke file log, sehingga Anda dapat mengikuti kemajuan skrip (misalnya menggunakan tail
)?
EDIT Ternyata yang python -u script.py
melakukan trik, saya tidak tahu tentang buffering stdout.
Jawaban:
Hal ini terjadi karena biasanya ketika proses STDOUT dialihkan ke sesuatu selain terminal, maka output buffer ke beberapa buffer berukuran khusus OS (mungkin 4k atau 8k dalam banyak kasus). Sebaliknya, ketika mengeluarkan ke terminal, STDOUT akan menjadi buffer-line atau tidak buffer sama sekali, sehingga Anda akan melihat output setelah masing
\n
- masing atau untuk setiap karakter.Anda biasanya dapat mengubah buffer STDOUT dengan
stdbuf
utilitas:Sekarang jika Anda
tail -F log
, Anda akan melihat setiap output garis segera setelah dihasilkan.Atau pembilasan eksplisit dari aliran output setelah setiap cetak harus mencapai hal yang sama. Sepertinya
sys.stdout.flush()
harus mencapai ini dengan Python. Jika Anda menggunakan Python 3.3 atau yang lebih baru, yangprint
fungsi juga memilikiflush
kata kunci yang melakukan hal ini:print('hello', flush=True)
.sumber
python -u script.py
itu yang berhasil. EDIT Begitu banyak jawaban sekaligus, saya menerima jawaban Anda karena itu menunjuk saya ke arah penyangga.--line-buffered
untukgrep
, tetapi beberapa yang lain tidak.stdbuf
adalah utilitas catchall umum untuk menangani mereka yang tidak.stdbuf -o0 python script.py > log
dalam keadaan yang ditentukan seperti ini?-oL
adalah kompromi. Secara umum buffer yang lebih besar akan memberikan kinerja yang lebih baik ketika mengarahkan ulang suatu tempat (lebih sedikit panggilan sistem dan lebih sedikit operasi I / O). Namun jika benar-benar diperlukan untuk melihat setiap karakter seperti yang dihasilkan maka ya,-o0
akan diperlukan.Ini harus melakukan pekerjaan:
Karena Python akan buffer
stdout
secara default, di sini saya telah menggunakansys.stdout.flush()
flush buffer.Solusi lain adalah dengan menggunakan
-u
saklar (unbuffered) daripython
. Jadi, yang berikut juga akan berlaku:sumber
Variasi pada tema menggunakan opsi python sendiri untuk keluaran unbuffered akan digunakan
#!/usr/bin/python -u
sebagai baris pertama.Dengan
#!/usr/bin/env python
argumen tambahan itu tidak akan berfungsi, maka sebagai alternatif, seseorang dapat menjalankanPYTHONUNBUFFERED=1 ./my_scriipt.py > output.txt
atau melakukannya dalam dua langkah:sumber
Anda harus beralih
flush=True
keprint
fungsi:Menurut dokumentasi, secara default,
print
tidak menerapkan apa pun tentang pembilasan:Dan dokumentasi untuk
sys
strems mengatakan:Jika Anda terjebak dengan versi python kuno, Anda harus memanggil
flush
metodesys.stdout
stream:sumber
DigitalTrauma
dikatakan 10 jam sebelumnya. Anda harus memperbaiki posnya, bukan memposting hal yang sama lagi.print(flush=True)
ditambahkan ke jawaban setelah saya oleh penulis pihak ketiga. Saya merasa tidak enak untuk merobek konten dari jawaban saya untuk meletakkannya di yang lain tanpa kredit. Saya memutuskan untuk menambahkan jawaban saya semata-mata karena tidak ada jawaban yang menyebutkan cara paling sederhana untuk mencapai apa yang diinginkan OP dalam versi python yang lebih baru, dan saya menambahkan "cara lama" hanya untuk kelengkapan. Lain kali silakan periksa riwayat revisi sebelum berkomentar dan atau downvoting.__future__
impor:from __future__ import print_function
. Tapi ya, itu hanya untuk kompatibilitas dengan Python 3