2009-12-13 17 views
6

मुझे पाइथन में धागे और टेम्पफाइल मॉड्यूल के साथ एक दिलचस्प समस्या है। धागे से बाहर निकलने तक कुछ साफ नहीं हो रहा है, और मैं एक खुली फ़ाइल सीमा के खिलाफ चल रहा हूं। (यह ओएस एक्स 10.5.8, पायथन 2.5.1 पर है।)पायथन tempfile मॉड्यूल और धागे अच्छा खेल नहीं रहे हैं; मैं क्या गलत कर रहा हूं?

फिर भी अगर मैं दोहराना चाहता हूं कि tempfile मॉड्यूल क्या कर रहा है (सभी सुरक्षा जांच नहीं, बल्कि सिर्फ फाइल डिस्क्रिप्टर उत्पन्न करना और फिर ओएस का उपयोग करना। फ़ाइल ऑब्जेक्ट बनाने के लिए fdopen) मुझे कोई समस्या नहीं है।

इसे पायथन के साथ एक बग के रूप में दर्ज करने से पहले, मुझे लगा कि मैं यहां जांच करूंगा, क्योंकि यह बहुत अधिक संभावना है कि मैं कुछ गलत कर रहा हूं। लेकिन अगर मैं हूं, तो इसे समझने की कोशिश करने का एक दिन मुझे कहीं भी नहीं मिला है।

#!/usr/bin/python 

import threading 
import thread 
import tempfile 
import os 
import time 
import sys 

NUM_THREADS = 10000 

def worker_tempfile(): 
    tempfd, tempfn = tempfile.mkstemp() 
    tempobj = os.fdopen(tempfd, 'wb') 
    tempobj.write('hello, world') 
    tempobj.close() 
    os.remove(tempfn) 
    time.sleep(10) 

def worker_notempfile(index): 
    tempfn = str(index) + '.txt' 
    # The values I'm passing os.open may be different than tempfile.mkstemp 
    # uses, but it works this way as does using the open() function to create 
    # a file object directly. 
    tempfd = os.open(tempfn, 
        os.O_EXCL | os.O_CREAT | os.O_TRUNC | os.O_RDWR) 
    tempobj = os.fdopen(tempfd, 'wb') 
    tempobj.write('hello, world') 
    tempobj.close() 
    os.remove(tempfn) 
    time.sleep(10) 

def main(): 
    for count in range(NUM_THREADS): 
     if count % 100 == 0: 
      print('Opening thread %s' % count) 
     wthread = threading.Thread(target=worker_tempfile) 
     #wthread = threading.Thread(target=worker_notempfile, args=(count,)) 
     started = False 
     while not started: 
      try: 
       wthread.start() 
       started = True 
      except thread.error: 
       print('failed starting thread %s; sleeping' % count) 
       time.sleep(3) 

if __name__ == '__main__': 
    main() 

अगर मैं worker_notempfile लाइन सक्रिय और worker_tempfile लाइन टिप्पणी की-आउट के साथ इसे चलाने के लिए, यह पूरा करने चलाता है।

दूसरी तरह के आसपास (worker_tempfile उपयोग करते हुए) मैं निम्न त्रुटि हो:

$ python threadtempfiletest.py 
Opening thread 0 
Opening thread 100 
Opening thread 200 
Opening thread 300 
Exception in thread Thread-301: 
Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 460, in __bootstrap 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 440, in run 
    File "threadtempfiletest.py", line 17, in worker_tempfile 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 302, in mkstemp 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 236, in _mkstemp_inner 
OSError: [Errno 24] Too many open files: '/var/folders/4L/4LtD6bCvEoipksvnAcJ2Ok+++Tk/-Tmp-/tmpJ6wjV0' 

कोई भी विचार क्या मैं गलत कर रहा हूँ? क्या यह पाइथन में एक बग है, या क्या मैं हड्डी का नेतृत्व कर रहा हूं?

अद्यतन 2009-12-14: मुझे लगता है कि मुझे जवाब मिल गया है, लेकिन मुझे यह पसंद नहीं है। चूंकि कोई भी समस्या को दोहराने में सक्षम नहीं था, इसलिए मैं मशीनों के लिए हमारे कार्यालय के चारों ओर शिकार कर रहा था। यह मेरी मशीन को छोड़कर सब कुछ पर पारित किया। मैंने मैक पर उसी सॉफ़्टवेयर संस्करणों का परीक्षण किया था जिसका उपयोग मैं कर रहा था। मैं भी एक ही हार्डवेयर और सॉफ्टवेयर कॉन्फ़िगरेशन के साथ एक डेस्कटॉप जी 5 के लिए शिकार चला गया - एक ही परिणाम। दोनों परीक्षण (tempfile और tempfile के साथ) सब कुछ पर सफल रहा।

किक्स के लिए, मैंने पायथन 2.6.4 डाउनलोड किया, और इसे अपने डेस्कटॉप पर और पायथन 2.5.1 के रूप में मेरे सिस्टम पर एक ही पैटर्न की कोशिश की: tempfile विफल रहा, और notempfile सफल हुआ।

यह मुझे इस निष्कर्ष पर पहुंचा रहा है कि मेरे मैक पर कुछ हुआ है, लेकिन मुझे यकीन है कि क्या पता नहीं लगा सकता। किसी भी सुझाव का स्वागत है।

+1

मदद नहीं कर सकता, लेकिन अच्छे कोड के साथ स्पष्ट प्रश्न के लिए +1। –

+0

क्या आप हमें पाइथन संस्करण दे सकते हैं, कृपया? मुझे नहीं पता कि यह मायने रखता है, लेकिन यह हो सकता है। –

+0

जोनाथन: बहुत बहुत धन्यवाद! पीटर: पायथन 2.5.1। मैंने इसे प्रतिबिंबित करने के लिए प्रश्न भी संपादित किया है। – Schof

उत्तर

0

चूंकि कोई भी समस्या को दोहराने में सक्षम नहीं था, इसलिए मैं मशीनों के लिए हमारे कार्यालय के आसपास शिकार कर रहा था। यह मेरी मशीन को छोड़कर सब कुछ पर पारित किया। मैंने मैक पर उसी सॉफ़्टवेयर संस्करणों का परीक्षण किया था जिसका उपयोग मैं कर रहा था। मैं भी एक ही हार्डवेयर और सॉफ्टवेयर कॉन्फ़िगरेशन के साथ एक डेस्कटॉप जी 5 के लिए शिकार चला गया - एक ही परिणाम। दोनों परीक्षण (tempfile और tempfile के साथ) सब कुछ पर सफल रहा।

किक्स के लिए, मैंने पायथन 2.6.4 डाउनलोड किया, और इसे अपने डेस्कटॉप पर और पायथन 2.5.1 के रूप में मेरे सिस्टम पर एक ही पैटर्न की कोशिश की: tempfile विफल रहा, और notempfile सफल हुआ।

यह मुझे इस निष्कर्ष पर पहुंचा रहा है कि मेरे मैक पर कुछ हुआ है, इसलिए यह कोई समस्या नहीं होने की संभावना है कि कोई और कभी भी चलता है।

धन्यवाद हर किसी के लिए बहुत कुछ (विशेष रूप से एलेक्स मार्टेलि) जिन्होंने इस पर मदद की!

3

मुझे लगता है कि आपका उत्तर here पाया जा सकता है। आपको स्पष्ट रूप से os.close() फ़ाइल डिस्क्रिप्टर को ट्यूपल के पहले भाग के रूप में दिया गया है जो mkstemp आपको देता है।

संपादित करें: नहीं, ओपी पहले ही कर रहा है जो किया जाना चाहिए। मैं अच्छे लिंक के लिए जवाब छोड़ रहा हूँ।

+1

लेकिन वह पोस्ट कहती है "फ़ंक्शन os.fdopen (fd) वापस आ जाएगा एक ही फाइल डिस्क्रिप्टर का उपयोग कर एक पाइथन फ़ाइल ऑब्जेक्ट। उस फ़ाइल ऑब्जेक्ट को बंद करना ओएस-स्तरीय फ़ाइल डिस्क्रिप्टर को बंद कर देगा "- जो (या मेरे ज्ञान का सबसे अच्छा होना चाहिए) सही है और यही कारण है कि ओपी का बग इतना रहस्यमय है ... वह ** ** fdopen' का उपयोग कर रहा है और फिर फ़ाइल ऑब्जेक्ट को बंद कर रहा है ... और फिर भी वह फाइल डिस्क्रिप्टर को लीक कर रहा है, जो एक गंभीर रहस्य है! –

+0

डी ओह! सुधार के लिए धन्यवाद। मैं यह जवाब छोड़ दूंगा , सिर्फ इसलिए कि यह संसाधन उपयोगी है। –

+0

मुझे एहसास है कि यह पोस्ट पुराना है, लेकिन यह मुझे एक ही मुद्दे पर बाहर निकाल दिया गया है। यह बहुत ही अनजान है क्योंकि बग्स जाते हैं। आपको लगता है कि जब फ़ाइल डिस्क्रिप्टर 'mkstemp से लौटाया गया () '' गुंजाइश से बाहर हो जाता है, सबकुछ खुद के बाद साफ हो जाएगा ... लेकिन कुछ मशीनों पर, यह समानांतर लूप खत्म होने तक नहीं होता है। निम्न उदाहरण आपकी मशीन को यह सोचने के लिए एक अच्छा तरीका दिखाता है कि इसकी डिस्क पूरी होने पर पूर्ण हो गई है। फ़ाइलों * वास्तव में रास्ते में नष्ट हो गए हैं, लेकिन जब तक प्रोग्राम बाहर निकलता है तब तक ओएस इसे महसूस नहीं करता है। https: //gist.github।com/ejhumphrey/b556c8be89fb6d5aeed1 –

4

मैक ओएस एक्स 10.5.9 पर समस्या (ऐप्पल के स्वयं के निर्माण) के साथ समस्या को पुन: उत्पन्न करने में असमर्थ हूं - पूरा होने के लिए रन!

मैंने मैकबुक प्रो, यानी, एक इंटेल प्रोसेसर, और एक पुराना पावरमैक, यानी, एक पीपीसी प्रोसेसर दोनों की कोशिश की है।

तो मैं केवल कल्पना कर सकता हूं कि 10.5.8 में एक बग होना चाहिए जो मैंने कभी नहीं देखा (परीक्षण के लिए लगभग 10.5.8 नहीं है, क्योंकि जब भी सॉफ़्टवेयर अपडेट इसे ऑफ़र करता है तो मैं तुरंत अपग्रेड करता हूं)। मैं बस सुझाव दे सकता हूं कि आप 10.5.9 तक अपग्रेड करने का प्रयास करें और देखें कि बग गायब हो गया है - अगर ऐसा नहीं होता है, तो मुझे नहीं पता कि मेरी मशीनों और आपके बीच यह व्यवहार अंतर कैसे संभव है।

+0

हम्म। प्रतीत होता है कि 10.5.8 नवीनतम संस्करण सॉफ़्टवेयर अपडेट होगा। शायद यह एक पावरपीसी बनाम इंटेल चीज है? (मैं पावरपीसी पर हूं।) – Schof

+0

ऐप्पल 2.5.1 के साथ 10.5.8 पीपीसी पर मेरे लिए असफल नहीं है। –

+0

10.5.8 * * एप्पल की वेबसाइट पर सूचीबद्ध नवीनतम संस्करण है। 10.5.9 प्री-रिलीज संस्करण है? – Schof

1

मैंने अभी अपने उबंटू लिनक्स कंप्यूटर पर अपने कोड का परीक्षण किया है, और यह मेरे लिए पूरी तरह से काम करता है।

मेरे पास आपके लिए प्रयास करने का एक सुझाव है। मुझे नहीं पता कि इससे मदद मिलेगी लेकिन यह चोट नहीं पहुंचा सकती है। साथ उपयोग करने के लिए अपने कोड पुनर्लेखन:

from __future__ import with_statement 

def worker_tempfile(): 
    tempfd, tempfn = tempfile.mkstemp() 
    with os.fdopen(tempfd, 'wb') as tempobj: 
     tempobj.write('hello, world') 
    os.remove(tempfn) 
    time.sleep(10) 

with बयान सुनिश्चित करें कि फ़ाइल वस्तु कोई बात नहीं क्या आप बंद हो जाता है बनाने के लिए माना जाता है। शायद यह मदद कर सकता है?

शुभकामनाएं। रास्ते पर सवाल पर महान काम।

1

आपको क्यों लगता है कि त्रुटि वास्तविक नहीं है? आप 10000 धागे लॉन्च कर रहे हैं, प्रत्येक फ़ाइल खोल रहा है, जबकि खुली फाइलों की अधिकतम संख्या आमतौर पर यूनिक्स सिस्टम के तहत 1024 है।

सबसे पहले वर्तमान में खुले फ़ाइलों की संख्या को मैन्युअल रूप से ट्रैक करने की जांच करें और जांचें कि क्या यह ओएस सीमा से पहले है।

+0

मुझे लगता है कि यह एक पायथन बग (या मेरे कोड में एक त्रुटि) हो सकता है क्योंकि एक फ़ंक्शन विफल रहता है (worker_tempfile) जबकि लगभग बराबर समकक्ष फ़ंक्शन सफल होता है (worker_notempfile)। – Schof

+0

यह बहुत कमजोर कारण है। विभिन्न कार्यान्वयन के साथ विभिन्न कार्यों (बिल्टिन ओएस। * फ़ंक्शंस या पायथन-लिखित टेम्पफाइल। * फ़ंक्शंस) को कॉल करना, चीजों को समांतर बनाने के तरीके पर बहुत अधिक प्रभाव डाल सकता है। यही कारण है कि मैं आपको यह जांचने का सुझाव देता हूं कि त्रुटि वास्तविक नहीं है। –

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