簡體   English   中英

在Windows上的Python 2.5中下載時,urlopen錯誤10045,'地址已在使用'

[英]urlopen error 10045, 'address already in use' while downloading in Python 2.5 on Windows

我正在編寫將在Linux,OS X和Windows上運行的代碼。 它從服務器下載大約55,000個文件的列表,然后逐步檢查文件列表,檢查文件是否存在於本地。 (使用SHA哈希驗證和一些其他好東西。)如果文件不在本地存在或哈希不匹配,則下載它們。

服務器端在Ubuntu上通過端口80是普通的Apache 2。

客戶端在Mac和Linux上運行良好,但在下載了大量文件后,在Windows(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指向我的TCP端口耗盡,但“netstat -n “從來沒有在”TIME_WAIT“狀態下向我顯示超過六個連接,即使在它出錯之前。

代碼(對於它下載的55,000個文件中的每一個都調用一次)是這樣的:

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

更新:我通過greping日志發現它正好進入下載例程3998次。 我已經多次運行它,每次都失敗了3998。 鑒於鏈接文章指出可用端口是5000-1025 = 3975(有些可能已到期並被重用),它開始看起來更像鏈接文章描述真正的問題。 但是,我仍然不確定如何解決這個問題。 進行注冊表編輯不是一種選擇。

如果它確實是一個資源問題(釋放os套接字資源)

試試這個:

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

如果你想要你可以插入一個睡眠,或者你可以依賴它

在我的win-xp上問題沒有出現(我下載了5000次)

我通過進程黑客觀察我的進程和網絡。

在框外思考,你似乎試圖解決的問題已經被一個名為rsync的程序解決了。 您可能會查找Windows實施,看看它是否滿足您的需求。

您應該認真考慮復制和修改此pyCurl示例,以便有效下載大量文件。

你應該真正使用持久的HTTP連接,而不是為每個請求打開一個新的TCP連接 - 看看urlgrabber (或者只是在keepalive.py上看看如何為urllib2添加keep-alive連接支持)。

所有跡象都表明缺少可用的插座。 你確定只有6個處於TIME_WAIT狀態嗎? 如果您正在運行如此多的下載操作,netstat很可能會超出您的終端緩沖區。 我發現netstat stat在正常使用期間超出了我的終端。

解決方案是修改代碼以重用套接字。 或者引入超時。 跟蹤你有多少個開放插座也沒什么壞處。 優化等待。 Windows XP的默認超時為120秒。 如果你的插座耗盡,你至少要睡這么長時間。 不幸的是,當套接字關閉並離開TIME_WAIT狀態時,看起來很容易從Python檢查。

鑒於請求和超時的異步性質,執行此操作的最佳方法可能是在一個線程中。 使每個威脅在完成之前睡眠2分鍾。 您可以使用信號量或限制活動線程數,以確保不會耗盡套接字。

這是我如何處理它。 您可能希望將異常子句添加到fetch部分的內部try塊,以警告您有關失敗的提取。

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

對不起,我的python有點生疏,所以如果我錯過了什么,我不會感到驚訝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM