Seberapa sering python menyiram ke file?

228
  1. Seberapa sering Python menyiram ke file?
  2. Seberapa sering Python flush ke stdout?

Saya tidak yakin tentang (1).

Adapun (2), saya percaya Python flushes ke stdout setelah setiap baris baru. Tetapi, jika Anda kelebihan stdout untuk menjadi file, apakah sering flush?

Tim McJilton
sumber

Jawaban:

332

Untuk operasi file, Python menggunakan buffering sistem operasi standar kecuali jika Anda mengkonfigurasinya, lakukan sebaliknya. Anda dapat menentukan ukuran buffer, tidak dibuat buffer, atau buffer baris.

Sebagai contoh, fungsi terbuka mengambil argumen ukuran buffer.

http://docs.python.org/library/functions.html#open

"Argumen buffering opsional menentukan ukuran buffer yang diinginkan file:"

  • 0 berarti tidak terbaca,
  • 1 berarti garis buffered,
  • nilai positif lainnya berarti menggunakan buffer (kurang-lebih) ukuran itu.
  • Buffer negatif berarti menggunakan default sistem, yang biasanya buffer baris untuk perangkat tty dan buffering penuh untuk file lain.
  • Jika dihilangkan, standar sistem digunakan.

kode:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)
Corey Goldberg
sumber
23
+1 untuk bagian "line buffered". Itulah tepatnya yang saya cari dan itu bekerja seperti pesona.
pasang kembali
2
Menggunakan Python 3.4.3 ketika saya melakukannya open('file.txt', 'w', 1)saya mendapatkan garis buffering yang tepat. Tetapi jika saya melakukan sesuatu yang lebih besar (saya ingin open('file.txt', 'w', 512)) itu buffer penuh io.DEFAULT_BUFFER_SIZE8192. Apakah itu bug Python, bug Linux, atau bug ID10t?
Bruno Bronosky
Apakah mungkin untuk mengubah buffering untuk stream yang sudah dibuka ? Katakanlah, saya ingin stdoutmenjadi buffer-line terlepas dari apakah itu konsol atau diarahkan ke file?
Mikhail T.
1
@CharlieParker ketika Anda memanggil write()file handle, outputnya buffered di memori dan diakumulasikan hingga buffer penuh ... pada saat itu buffer "flushed" (konten ditulis dari buffer ke file). Anda dapat secara eksplisit membersihkan buffer dengan memanggil flush()metode pada pegangan file.
Corey Goldberg
3
Perhatikan bahwa unbuffered (0) hanya tersedia dalam mode biner dan line buffered (1) hanya tersedia dalam mode teks.
ZaydH
172

Anda juga dapat memaksa flush buffer ke file secara terprogram dengan flush()metode ini.

with open('out.log', 'w+') as f:
    f.write('output is ')
    # some work
    s = 'OK.'
    f.write(s)
    f.write('\n')
    f.flush()
    # some other work
    f.write('done\n')
    f.flush()

Saya telah menemukan ini berguna ketika mengekor file keluaran dengan tail -f .

kortina
sumber
54
Dari dokumen:Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
1
@bobismijnnaam tautan lain kali ke dokumen tersebut. Hanya referensi yang dapat saya temukan dari github.com/jprzywoski/python-reference/blob/master/source/docs/… dan saya tidak tahu siapa itu.
Bruno Bronosky
5
@ Bruno Bronosky Poin bagus. Docs: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam
apa yang saya bingung adalah apa arti istilah itu flushing. Mengapa kita membutuhkannya? Untuk apa ini? mengapa saya harus peduli?
Charlie Parker
@CharlieParker ketika Anda menulis, Anda menulis ke salinan (bagian dari) file dalam RAM, yang mungkin tidak disimpan ke disk untuk sementara waktu. Ini meningkatkan kinerja, tetapi bisa berarti kehilangan data jika salinan itu tidak pernah ditulis (disk dihapus, OS lumpuh, dll). flush () memberitahu Python untuk segera menulis buffer itu kembali ke disk. (Lalu, os.fsync () memberitahu OS untuk juga melakukannya. Ada banyak lapisan buffer ...)
Rena
13

Saya tidak tahu apakah ini berlaku untuk python juga, tapi saya pikir itu tergantung pada sistem operasi yang Anda jalankan.

Di Linux misalnya, output ke terminal mem-flush buffer pada baris baru, sedangkan untuk output ke file hanya mem-flush ketika buffer penuh (secara default). Ini karena lebih efisien untuk menyiram buffer lebih sedikit, dan pengguna cenderung tidak memperhatikan jika output tidak memerah pada baris baru dalam file.

Anda mungkin dapat membersihkan secara otomatis output jika itu yang Anda butuhkan.

EDIT: Saya pikir Anda akan otomatis flush di python dengan cara ini (berdasarkan dari sini )

#0 means there is no buffer, so all output
#will be auto-flushed
fsock = open('out.log', 'w', 0)
sys.stdout = fsock
#do whatever
fsock.close()
KLee1
sumber
12

Anda juga dapat memeriksa ukuran buffer default dengan memanggil atribut DEFAULT_BUFFER_SIZE hanya baca dari modul io.

import io
print (io.DEFAULT_BUFFER_SIZE)
N Randhawa
sumber
1
Terima kasih! Adalah baik untuk mengetahui bahwa python menetapkannya sebagai OS mendefinisikan ... tetapi ini membantu mencari tahu apa yang OS mendefinisikan sebelumnya.
Cometsong
2

Berikut adalah pendekatan lain, hingga OP untuk memilih mana yang lebih disukai.

Ketika memasukkan kode di bawah ini dalam __init__file .py sebelum kode lain, pesan yang dicetak dengan printdan kesalahan apa pun tidak akan lagi dicatat ke Ableton's Log.txt tetapi untuk memisahkan file pada disk Anda:

import sys

path = "/Users/#username#"

errorLog = open(path + "/stderr.txt", "w", 1)
errorLog.write("---Starting Error Log---\n")
sys.stderr = errorLog
stdoutLog = open(path + "/stdout.txt", "w", 1)
stdoutLog.write("---Starting Standard Out Log---\n")
sys.stdout = stdoutLog

(untuk Mac, ubah #username# nama folder pengguna Anda. Di Windows jalur ke folder pengguna Anda akan memiliki format yang berbeda)

Ketika Anda membuka file dalam editor teks yang menyegarkan kontennya ketika file pada disk diubah (contoh untuk Mac: TextEdit tidak tetapi TextWrangler tidak), Anda akan melihat log diperbarui secara real-time.

Penghargaan: kode ini sebagian besar disalin dari skrip permukaan kontrol liveAPI oleh Nathan Ramella

Mattijs
sumber