หลามทำความสะอาดไฟล์บ่อยแค่ไหน?


228
  1. Python ล้างข้อมูลในไฟล์บ่อยแค่ไหน?
  2. Python ล้างข้อมูลเพื่อ stdout บ่อยเพียงใด

ฉันไม่แน่ใจเกี่ยวกับ (1)

สำหรับ (2) ฉันเชื่อว่า Python จะล้างออกเพื่อ stdout หลังจากทุกบรรทัดใหม่ แต่ถ้าคุณโอเวอร์โหลด stdout ไปที่ไฟล์มันจะล้างบ่อยไหม?

คำตอบ:


332

สำหรับการทำงานของไฟล์ Python ใช้การบัฟเฟอร์เริ่มต้นของระบบปฏิบัติการเว้นแต่คุณจะกำหนดค่าไว้ คุณสามารถระบุขนาดบัฟเฟอร์ไม่บัฟเฟอร์หรือบัฟเฟอร์บรรทัด

ตัวอย่างเช่นฟังก์ชั่นเปิดใช้เวลาอาร์กิวเมนต์ขนาดบัฟเฟอร์

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

"อาร์กิวเมนต์บัฟเฟอร์ทางเลือกระบุขนาดบัฟเฟอร์ที่ต้องการของไฟล์:"

  • 0 หมายถึงไม่มีข้อผิดพลาด
  • 1 หมายถึงบัฟเฟอร์บรรทัด
  • ค่าบวกอื่น ๆ หมายถึงการใช้บัฟเฟอร์ของ (โดยประมาณ) ขนาดนั้น
  • การบัฟเฟอร์เชิงลบหมายถึงการใช้ค่าเริ่มต้นของระบบซึ่งโดยปกติจะเป็นบรรทัดบัฟเฟอร์สำหรับอุปกรณ์ tty และบัฟเฟอร์เต็มสำหรับไฟล์อื่น ๆ
  • หากไม่ระบุจะใช้ค่าเริ่มต้นของระบบ

รหัส:

bufsize = 0
f = open('file.txt', 'w', buffering=bufsize)

23
+1 สำหรับส่วน "line buffered" นั่นคือสิ่งที่ฉันกำลังมองหาและมันใช้งานได้อย่างมีเสน่ห์
rein

2
การใช้ Python 3.4.3 เมื่อopen('file.txt', 'w', 1)ฉันได้รับบัฟเฟอร์บรรทัดที่เหมาะสม แต่ถ้าฉันทำสิ่งที่ใหญ่กว่านี้ (ฉันต้องการopen('file.txt', 'w', 512)) มันจะบัฟเฟอร์เต็มio.DEFAULT_BUFFER_SIZE8192 นั่นคือข้อผิดพลาด Python, ข้อผิดพลาด Linux หรือข้อผิดพลาด ID10t?
Bruno Bronosky

เป็นไปได้หรือไม่ที่จะเปลี่ยนการกำหนดบัฟเฟอร์สำหรับสตรีมที่เปิดอยู่แล้ว ? บอกว่าฉันต้องการstdoutที่จะบัฟเฟอร์บรรทัดโดยไม่คำนึงว่ามันเป็นคอนโซลหรือเปลี่ยนเส้นทางไปยังไฟล์หรือไม่?
มิคาอิลต.

1
@CharlieParker เมื่อคุณเรียกwrite()ใช้ตัวจัดการไฟล์เอาต์พุตจะถูกบัฟเฟอร์ในหน่วยความจำและสะสมจนบัฟเฟอร์เต็ม ... เวลาที่บัฟเฟอร์ได้รับ "flushed" (เนื้อหาถูกเขียนจากบัฟเฟอร์ไปยังไฟล์) คุณสามารถล้างบัฟเฟอร์อย่างชัดเจนโดยเรียกflush()วิธีการในการจัดการไฟล์
Corey Goldberg

3
โปรดทราบว่า unbuffered (0) ใช้ได้เฉพาะในโหมดไบนารีและบัฟเฟอร์บรรทัด (1) จะใช้ได้เฉพาะในโหมดข้อความ
ZaydH

172

นอกจากนี้คุณยังสามารถบังคับให้ล้างบัฟเฟอร์ไปยังแฟ้มโดยทางโปรแกรมด้วยflush()วิธีการ

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()

ฉันได้พบว่ามีประโยชน์นี้เมื่อ tailing tail -fไฟล์ที่ส่งออกด้วย


54
จากเอกสาร: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 ครั้งต่อไปลิงก์ไปยังเอกสารดังกล่าว การอ้างอิงเท่านั้นที่ฉันสามารถหาได้จากgithub.com/jprzywoski/python-reference/blob/master/source/docs/…และฉันไม่รู้ว่าใครเป็นใคร
Bruno Bronosky

5
@Bruno Bronosky จุดที่ดี เอกสาร: Note: flush() does not necessarily write the file’s data to disk. Use flush() followed by os.fsync() to ensure this behavior.
bobismijnnaam

สิ่งที่ฉันสับสนคือสิ่งที่คำflushingว่าหมายถึง ทำไมเราต้องการมัน? มีไว้เพื่ออะไร? ทำไมฉันถึงต้องแคร์?
Charlie Parker

@CharlieParker เมื่อคุณเขียนคุณเขียนไปยังสำเนา (ส่วนหนึ่งของ) ไฟล์ใน RAM ซึ่งอาจไม่ถูกบันทึกลงดิสก์ในขณะที่ มันช่วยปรับปรุงประสิทธิภาพ แต่อาจหมายถึงการสูญเสียข้อมูลหากสำเนานั้นไม่ได้รับการเขียน (นำดิสก์ออกแล้วระบบขัดข้อง ฯลฯ ) flush () บอก Python ให้เขียนบัฟเฟอร์นั้นกลับไปที่ดิสก์ทันที (จากนั้น os.fsync () บอกให้ระบบปฏิบัติการทำเช่นนั้นมีบัฟเฟอร์หลายเลเยอร์ ... )
Rena

13

ฉันไม่ทราบว่าสิ่งนี้ใช้ได้กับงูใหญ่เช่นกัน แต่ฉันคิดว่ามันขึ้นอยู่กับระบบปฏิบัติการที่คุณใช้งานอยู่

บน Linux ตัวอย่างเช่นเอาต์พุตไปยังเทอร์มินัลล้างบัฟเฟอร์ในบรรทัดใหม่ขณะที่เอาต์พุตไปยังไฟล์จะล้างเฉพาะเมื่อบัฟเฟอร์เต็ม (โดยค่าเริ่มต้น) นี่เป็นเพราะมันจะมีประสิทธิภาพมากขึ้นในการล้างบัฟเฟอร์น้อยลงและผู้ใช้มีโอกาสน้อยที่จะสังเกตเห็นว่าการส่งออกไม่ได้ล้างบนบรรทัดใหม่ในไฟล์

คุณอาจสามารถล้างเอาต์พุตอัตโนมัติถ้านั่นคือสิ่งที่คุณต้องการ

แก้ไข: ฉันคิดว่าคุณจะล้างอัตโนมัติใน python ด้วยวิธีนี้ (จากที่นี่ )

#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()

12

คุณยังสามารถตรวจสอบขนาดบัฟเฟอร์เริ่มต้นได้ด้วยการเรียกใช้แอตทริบิวต์ DEFAULT_BUFFER_SIZE แบบอ่านอย่างเดียวจากโมดูล io

import io
print (io.DEFAULT_BUFFER_SIZE)

1
ขอบคุณ! มันเป็นเรื่องดีที่จะรู้ว่าชุดหลามเป็นกำหนด OS ... แต่นี้จะช่วยให้หาสิ่งที่ระบบปฏิบัติการก่อนกำหนด
Cometsong

2

นี่คือวิธีการอื่นจนถึง OP เพื่อเลือกสิ่งที่เขาต้องการ

เมื่อรวมรหัสด้านล่างใน__init__ไฟล์. py ก่อนรหัสอื่นข้อความที่พิมพ์ด้วยprintและข้อผิดพลาดใด ๆ จะไม่ถูกบันทึกลงใน Log.txt ของ Ableton อีกต่อไป แต่จะแยกไฟล์ต่าง ๆ ในดิสก์ของคุณ:

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

(สำหรับ Mac ให้เปลี่ยน #username#เป็นชื่อโฟลเดอร์ผู้ใช้ของคุณบน Windows เส้นทางไปยังโฟลเดอร์ผู้ใช้ของคุณจะมีรูปแบบที่แตกต่างกัน)

เมื่อคุณเปิดไฟล์ในเท็กซ์เอดิเตอร์ที่รีเฟรชเนื้อหาเมื่อไฟล์บนดิสก์มีการเปลี่ยนแปลง (ตัวอย่างสำหรับ Mac: TextEdit ไม่ได้ แต่ TextWrangler ทำ) คุณจะเห็นบันทึกที่อัปเดตตามเวลาจริง

เครดิต: รหัสนี้ถูกคัดลอกมาส่วนใหญ่มาจากสคริปต์พื้นผิวการควบคุม liveAPI โดย Nathan Ramella

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.