2009-10-02 15 views
5

पर पायथन 2.5 में डाउनलोड करते समय 'पता पहले से उपयोग में है' मैं लिनक्स, ओएस एक्स और विंडोज पर चलने वाला कोड लिख रहा हूं। यह सर्वर से लगभग 55,000 फ़ाइलों की एक सूची डाउनलोड करता है, फिर फ़ाइलों की सूची के माध्यम से कदम उठाता है, यह जांचता है कि फ़ाइलें स्थानीय रूप से मौजूद हैं या नहीं। (एसएचए हैश सत्यापन और कुछ अन्य उपहारों के साथ।) यदि फाइलें स्थानीय रूप से मौजूद नहीं हैं या हैश मेल नहीं खाता है, तो यह उन्हें डाउनलोड करता है।urlopen त्रुटि 10045, विंडोज

सर्वर साइड पोर्ट पर Ubuntu पर सादे-वनिला अपाचे 2 है 80

ग्राहक के पक्ष मैक और लिनक्स पर पूरी तरह से काम करता है, लेकिन मुझे एक नंबर डाउनलोड करने के बाद विंडोज (XP और Vista) पर इस त्रुटि देता है

urllib2.URLError: <urlopen error <10048, 'Address already in use'>> 

यह लिंक: फ़ाइलों के टीसीपी पोर्ट थकावट के http://bytes.com/topic/python/answers/530949-client-side-tcp-socket-receiving-address-already-use-upon-connect अंक मुझे, लेकिन "netstat -n" कभी नहीं "TIME_WAIT" स्थिति में मुझे छह से अधिक कनेक्शन से पता चला है, यहां तक ​​कि बस से पहले ही बाहर errored।

request = urllib2.Request(file_remote_path) 
opener = urllib2.build_opener() 
datastream = opener.open(request) 
outfileobj = open(temp_file_path, 'wb') 
try: 
    while True: 
     chunk = datastream.read(CHUNK_SIZE) 
     if chunk == '': 
      break 
     else: 
      outfileobj.write(chunk) 
finally: 
    outfileobj = outfileobj.close() 
    datastream.close() 

अद्यतन:

कोड (55,000 फाइलों को इसके डाउनलोड से प्रत्येक के लिए एक बार कहा जाता है) यह है मैं लॉग greping है कि यह डाउनलोड दिनचर्या वास्तव में 3998 बार में प्रवेश करती है द्वारा पाते हैं। मैंने इसे कई बार चलाया है और यह हर बार 3 9 8 9 में विफल रहता है। यह देखते हुए कि लिंक किए गए आलेख में कहा गया है कि उपलब्ध बंदरगाह 5000-1025 = 3 9 75 (और कुछ शायद समाप्त हो रहे हैं और पुन: उपयोग किए जा रहे हैं) यह वास्तविक समस्या का वर्णन करने वाले लिंक की तरह बहुत अधिक दिखने लग रहा है। हालांकि, मुझे अभी भी यह सुनिश्चित नहीं है कि इसे कैसे ठीक किया जाए। रजिस्ट्री संपादन करना एक विकल्प नहीं है।

उत्तर

5

तो यह वास्तव में एक संसाधन समस्या (मुक्त कराने ओएस सॉकेट संसाधन)

है की कोशिश करें:

request = urllib2.Request(file_remote_path) 
opener = urllib2.build_opener() 

retry = 3 # 3 tries 
while retry : 
    try : 
     datastream = opener.open(request) 
    except urllib2.URLError, ue: 
     if ue.reason.find('10048') > -1 : 
      if retry : 
       retry -= 1 
      else : 
       raise urllib2.URLError("Address already in use/retries exhausted") 
     else : 
      retry = 0 
    if datastream : 
     retry = 0 

outfileobj = open(temp_file_path, 'wb') 
try: 
    while True: 
     chunk = datastream.read(CHUNK_SIZE) 
     if chunk == '': 
      break 
     else: 
      outfileobj.write(chunk) 
finally: 
    outfileobj = outfileobj.close() 
    datastream.close() 

अगर आप आप एक सोने सम्मिलित कर सकते हैं चाहते हैं या आप यह

निर्भर ओएस पर बना मेरी जीत-एक्सपी समस्या दिखाई नहीं दे रही है (मैं 5000 डाउनलोड तक पहुंच गया)

मैं process hacker के साथ अपनी प्रक्रियाओं और नेटवर्क को देखता हूं।

+0

हैकर को संसाधित करने के लिंक के लिए धन्यवाद – Natascha

1

बॉक्स के बाहर सोचते हुए, जिस समस्या को आप हल करने का प्रयास कर रहे हैं, उसे पहले से ही rsync नामक प्रोग्राम द्वारा हल किया जा चुका है। आप विंडोज कार्यान्वयन की तलाश कर सकते हैं और देख सकते हैं कि यह आपकी आवश्यकताओं को पूरा करता है या नहीं।

+0

कई कारणों से, पाइथन में इसका अपना संस्करण लिखना हमारे लिए सबसे अच्छा विकल्प है। Rsync की "हत्यारा सुविधा" आंशिक डाउनलोड है - केवल अलग-अलग फ़ाइलों के भाग भेजना। हम उस कार्यक्षमता को डुप्लिकेट नहीं कर रहे हैं; यह बस एक सूची चलता है और डाउनलोड पूरी तरह से फ़ाइलों को बदल दिया। हम एक सुंदर मामूली पहिया reinventing कर रहे हैं। – Schof

+0

इसके लायक होने के लिए, 'rsync -W' पूरी फाइलों की प्रतिलिपि बनाता है –

+0

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

1

आपको फाइलों के बड़े संग्रह की कुशल डाउनलोडिंग के लिए this pyCurl example की प्रतिलिपि बनाने और संशोधित करने पर गंभीरता से विचार करना चाहिए।

1
इसके बजाय प्रत्येक अनुरोध वास्तव में लगातार HTTP कनेक्शन का उपयोग करना चाहिए के लिए एक नया TCP कनेक्शन खोलने की

- urlgrabber पर एक नजर है (या वैकल्पिक रूप, बस के लिए keepalive.py में कैसे जीवित-रखें urllib2 के लिए कनेक्शन समर्थन जोड़ने के लिए)।

1

सभी संकेत उपलब्ध सॉकेट की कमी को इंगित करते हैं। क्या आप वाकई TIME_WAIT स्थिति में केवल 6 हैं? यदि आप इतने सारे डाउनलोड ऑपरेशन चला रहे हैं तो यह बहुत संभावना है कि नेटस्टैट आपके टर्मिनल बफर को ओवररन्स कर देगा। मुझे लगता है कि नेटस्टैट स्टेट सामान्य उपयोग अवधि के दौरान मेरे टर्मिनल को ओवररन्स करता है।

समाधान या तो सॉकेट का पुन: उपयोग करने के लिए कोड को संशोधित करना है। या एक टाइमआउट शुरू करें। यह आपके ट्रैक के कितने खुले सॉकेट का ट्रैक रखने के लिए भी चोट नहीं पहुंचाएगा। प्रतीक्षा अनुकूलित करने के लिए। विंडोज एक्सपी पर डिफ़ॉल्ट टाइमआउट 120 सेकंड है। इसलिए यदि आप सॉकेट से बाहर निकलते हैं तो आप कम से कम लंबे समय तक सोना चाहते हैं।दुर्भाग्य से ऐसा लगता है कि सॉकेट बंद होने पर और TIME_WAIT स्थिति छोड़ने पर पाइथन से जांचने का एक आसान तरीका है।

अनुरोधों और समय-सारिणी की असीमित प्रकृति को देखते हुए, ऐसा करने का सबसे अच्छा तरीका धागे में हो सकता है। प्रत्येक खतरा इसे समाप्त होने से 2 मिनट पहले सोएं। आप या तो सैमफोर का उपयोग कर सकते हैं या सक्रिय धागे की संख्या को सीमित कर सकते हैं ताकि आप यह सुनिश्चित कर सकें कि आप सॉकेट से बाहर नहीं निकलते हैं।

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

import time 
import threading 
import Queue 

# assumes url_queue is a Queue object populated with tuples in the form of(url_to_fetch, temp_file) 
# also assumes that TotalUrls is the size of the queue before any threads are started. 


class urlfetcher(threading.Thread) 
    def __init__ (self, queue) 
     Thread.__init__(self) 
     self.queue = queue 


    def run(self) 
     try: # needed to handle empty exception raised by an empty queue. 
      file_remote_path, temp_file_path = self.queue.get() 
      request = urllib2.Request(file_remote_path) 
      opener = urllib2.build_opener() 
      datastream = opener.open(request) 
      outfileobj = open(temp_file_path, 'wb') 
      try: 
       while True: 
        chunk = datastream.read(CHUNK_SIZE) 
        if chunk == '': 
         break 
        else: 
         outfileobj.write(chunk) 
      finally: 
       outfileobj = outfileobj.close() 
       datastream.close()  
       time.sleep(120) 
       self.queue.task_done() 

elsewhere: 


while url_queue.size() < TotalUrls: # hard limit of available ports. 
    if threading.active_threads() < 3975: # Hard limit of available ports 
     t = urlFetcher(url_queue) 
     t.start() 
    else: 
     time.sleep(2) 

url_queue.join() 

क्षमा करें, मेरा अजगर थोड़ा जंगली है, इसलिए अगर मुझे कुछ याद आया तो मुझे आश्चर्य नहीं होगा।

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