2012-03-22 33 views
15

मैं एक परीक्षण चला रहा हूं, और पाया कि फाइल वास्तव में तब तक लिखी नहीं जाती जब तक मैं प्रोग्राम को रद्द करने के लिए नियंत्रण-सी को नियंत्रित नहीं करता। क्या कोई समझा सकता है कि ऐसा क्यों होगा?जब तक मैं प्रोग्राम को रोक नहीं देता तब तक फ़ाइल कैसे लिखी नहीं जाती है?

मुझे उम्मीद है कि यह एक ही समय में लिखने की उम्मीद है, इसलिए मैं प्रक्रिया के बीच में फ़ाइल को पढ़ सकता था।

import os 
from time import sleep 

f = open("log.txt", "a+") 
i = 0 
while True: 
    f.write(str(i)) 
    f.write("\n") 
    i += 1 
    sleep(0.1) 
+0

पुन: "इसका कारण बताएं", देखने http://stackoverflow.com/questions/ 1450551/buffered-io-vs-unbuffered-io –

उत्तर

49

डिस्क पर लेखन धीमा है, इसलिए कई प्रोग्राम स्टोर बड़े हिस्से में लिखते हैं जो वे एक-बार लिखते हैं। इसे बफरिंग कहा जाता है, और जब आप फ़ाइल खोलते हैं तो पाइथन स्वचालित रूप से करता है।

जब आप फ़ाइल में लिखते हैं, तो आप वास्तव में स्मृति में "बफर" पर लिख रहे हैं। जब यह भर जाता है, तो पाइथन स्वचालित रूप से डिस्क पर लिख देगा। आप बता सकते हैं कि यह "अब डिस्क के लिए बफर में सब कुछ लिखने"

f.flush() 

यह काफी पूरी कहानी नहीं है के साथ है, क्योंकि ऑपरेटिंग सिस्टम शायद बफ़र जाएगा साथ ही लिखता है। आप यह बता

os.fsync(f.fileno()) 

अंत के साथ फ़ाइल के बफर लिखने के लिए कर सकते हैं, तो आप अजगर बता सकते हैं open(f, "w", 0) साथ एक विशेष फ़ाइल बफ़र होना नहीं या केवल open(f,"w", 1) के साथ एक 1-लाइन बफर रखने के लिए। स्वाभाविक रूप से, यह उस फ़ाइल पर सभी परिचालनों को धीमा कर देगा, क्योंकि लिखने धीमे हैं।

+0

+1 वास्तव में जानकारीपूर्ण – twneale

+4

ध्यान दें कि gratuitous 'fsync()' कताई-डिस्क ड्राइव वाले लैपटॉप वाले लोगों का झुकाव है जो अपनी बैटरी जीवन की देखभाल करते हैं। सामग्री को अन्य कार्यक्रमों के लिए दृश्यमान होने के लिए 'fsync()' को कॉल करने की आवश्यकता नहीं है; यह एक अप्रत्याशित रीबूट के बाद दृश्यता के करीब होने के करीब है (हालांकि यह आवश्यक रूप से पर्याप्त स्थिति नहीं है)। –

+0

@ चार्ल्स डफी: 'अन्य कार्यक्रमों के लिए सामग्री को देखने के लिए आपको fsync() को कॉल करने की आवश्यकता नहीं है: क्यों? मुझे लगता है कि यदि आपका प्रोग्राम समाप्त नहीं हुआ है, और अन्य प्रोग्राम फ़ाइल को पढ़ते हैं, तो इसकी सामग्री अपडेट नहीं की जा सकती है। –

5

फ़ाइल लिखने वाले बफर को फ़ाइल में फ़्लश करने के लिए आपको f.close() की आवश्यकता है। या आपके मामले में आप बस f.flush(); os.fsync(); करना चाहते हैं ताकि आप खुले फ़ाइल हैंडल के साथ लूपिंग रख सकें।

import os को न भूलें।

+0

... या 'f.flush()' –

+1

दरअसल, लेकिन यह os.fsync() – deed02392

+1

डिस्क के बिना डिस्क पर पूर्ण लेखन आउटपुट नहीं करता है , लेकिन अगर यह अन्य कार्यक्रमों के लिए दृश्यमान है, तो यही वह है जो वह यहां पूछ रहा है। os.fsync() महंगा है, और इसका उपयोग तब तक नहीं किया जाना चाहिए जब तक आप _really_ जानते हैं कि आप इसे चाहते हैं (और, आमतौर पर, उपयोगकर्ता को इसे बंद करने का एक तरीका है)। ध्यान दें कि यहां तक ​​कि अधिकांश डेटाबेस में fsync को अक्षम करने का एक तरीका होता है - कभी-कभी उपयोगकर्ता * चाहता है * चीजों को तेजी से बनाने के लिए डेटा भ्रष्टाचार को खतरे में डाल देता है। –

1

आप file.flush() की जाँच करना चाहते हैं - हालांकि ले ध्यान दें कि इस नहीं डिस्क पर डेटा लिखने सकता है, उद्धृत करने के लिए:

नोट: फ्लश() जरूरी करने के लिए फ़ाइल के डेटा लिखने नहीं है डिस्क। इस व्यवहार को सुनिश्चित करने के लिए os.fsync() के बाद फ्लश() का उपयोग करें।

फ़ाइल (file.close()) भी सुनिश्चित करेगा कि डेटा लिखा है समापन - with का उपयोग कर इस परोक्ष करना होगा, और आम तौर पर अधिक पठनीयता और स्पष्टता के लिए एक बेहतर विकल्प है - नहीं अन्य संभावित समस्याओं को सुलझाने का उल्लेख।

0

यह एक विंडोज़-आईएसएम है। यदि आप फ़ाइल के साथ पूर्ण होने पर एक स्पष्ट .close() जोड़ते हैं, तो वह उस समय एक्सप्लोरर में दिखाई देगा। यहां तक ​​कि बस इसे फ्लश करना पर्याप्त हो सकता है (मेरे पास परीक्षण करने के लिए एक विंडोज़ बॉक्स आसान नहीं है)। लेकिन मूल रूप से f.write वास्तव में लिखता नहीं है, यह केवल लिखने वाले बफर में संलग्न होता है - जब तक बफर फ़्लश नहीं हो जाता तब तक आप इसे नहीं देख पाएंगे।

यूनिक्स पर फ़ाइलें आमतौर पर इस स्थिति में 0-बाइट फ़ाइल के रूप में दिखाई देंगी।

0

फ़ाइल हैंडलर फ़्लश करने के लिए।

f.flush() 
0

फ़ाइल, लिखित नहीं प्राप्त करता है के रूप में उत्पादन बफर प्लावित हो रही नहीं है जब तक कचरा संग्रहण प्रभावी होता है, और (f.close() फोन करके संभावना से भी अधिक) मैं/हे बफर flushes।

वैकल्पिक रूप से, आपके लूप में, आप f.flush() पर os.fsync() पर कॉल कर सकते हैं, here दस्तावेज के रूप में।

f.flush() 
os.fsync() 

सभी ही कहा जा रहा है, अगर आप कभी भी अपने कोड के अन्य भागों साथ उस फ़ाइल में डेटा को साझा करने पर योजना, मैं अत्यधिक एक StringIO वस्तु का उपयोग कर की सिफारिश करेंगे।

1

आप लिखने के लिए बाध्य करने के लिए है, तो मैं मुझे यकीन है कि एक फ़ाइल में लिखा है बनाने के लिए निम्नलिखित लाइनों का उपयोग:

# Two commands together force the OS to store the file buffer to disc 
    f.flush() 
    os.fsync(f.fileno()) 
संबंधित मुद्दे

 संबंधित मुद्दे