0

この質問をするときに初心者のように見えるのは、これがマルチスレッドの最初の試みだからです。ごめん。

マルチスレッドはプロセスを高速化するためのものであるため、これでどこが間違っていたのかを理解しようとしています。私が最初に気付いたのは、「メインスレッド」スレッドが本来よりも非常に遅いことです (プロキシを使用していない唯一のスレッドです)。

プロセスがマルチスレッド化される前は、単一のプロセス/スレッドで 1 分以内に約 10 ~ 15 個の画像をダウンロードしていました。しかし現在、「マルチスレッド」(プロキシ経由で HTTP リクエストを送信しない唯一のスレッド) は実際には表示されません (ご覧のとおり: http://puu.sh/3KfwY.png )。それは最速のスレッドでなければなりません!

私の問題を明確に説明したことを願っています。:S

PS: プログラムの開始時に、15 秒以内に約 20 枚の写真をダウンロードします。ただし、その最初の起動後、プログラムは大幅に遅くなります。これがなぜなのかについてのアイデアはありますか?

#!/usr/bin/env python
import sys
import string
import os.path
import urllib.request
import threading
from time import gmtime, strftime, sleep
from random import choice

#list of our proxies
proxies = []

downloads = 1

#the number of files we want to download
target = int(sys.argv[1])

#argument 2 - proxies
try:
    sys.argv[2]
except:
    print('')
else:
    param = sys.argv[2]

    if param.find('.txt') != -1:
        print('Loading specified proxy list ('+ param +').')

        f = open(param, 'r+')
        print('Opening '+ f.name)
        proxylist = f.read()
        f.close()

        #split retrieved list by new line
        proxies = proxylist.split('\n')
    else:
        print('Single proxy specified.')
        proxies.append(param)


class thread(threading.Thread):
    def __init__(self, ID, name, proxy):
        threading.Thread.__init__(self)
        self.id = ID
        self.name = name
        self.downloads = 0
        self.proxy = proxy
        self.running = True
        self.fails = 0
    def run(self):
        global downloads

        if self.proxy != False:
            #id is always above one, so make the ID -1
            self.proxy = proxies[(self.id-1)]

            print(self.name +' initiating with proxy: '+self.proxy)

            #make our requests go through proxy
            self.p_handler = urllib.request.ProxyHandler({'http' : self.proxy})
            self.opener = urllib.request.build_opener(self.p_handler)
            urllib.request.install_opener(self.opener)
        else:
            print(self.name +' initiating without a proxy.')

        while downloads <= target and self.running:
            rstr = ''.join(choice(string.ascii_letters + string.digits) for x in range(5))

            url = 'http://puu.sh/'+rstr
            filename = 'downloaded/'+ strftime('%Y %m %d %H-%M-%S', gmtime()) +'.png';

            try:
                urllib.request.urlretrieve(url, filename)
            except urllib.request.HTTPError:
                pass
            except IOError:
                if self.fails > 10:
                    print(self.name +': Proxy is not working. Stopping thread.')
                    self.running = False

                self.fails += 1
            except:
                pass
            else:
                print(self.name +': downloading '+ filename+'...' + str(downloads))

                #if self.downloads % 10 == 0:
                #    print(self.name +': Sleeping a bit.')
                #    sleep(60)

                downloads += 1
                self.downloads += 1
                sleep(5)

#lets create the "downloaded" folder if it does not exist
if not os.path.isdir('downloaded'):
    try:
        os.mkdir('downloaded')
    except:
        pass

#thread count
thread_count = 1

#create threads, and initiate them
try:
    thread(0, 'main-thread', False).start()

    for x in proxies:
        thread(thread_count, 'Thread-'+str(thread_count), proxies[(thread_count-1)]).start()
        thread_count += 1
except:
    print('Couldn\'t start threads.')
4

1 に答える 1

0

実際の問題が何であるかはわかりませんが、私が気づいたことの 1 つは、あなたがurllib.request.install_opener. これにより、デフォルトのグローバルオープナーが設定されるため、すべてのスレッドに変更が表示されます。最初はほとんどのスレッドが割り当てられたプロキシを使用する可能性がありますが、その後はすべてのリクエストが同じプロキシに送られ、プロキシまたは何かによってスロットルされます。

sleep(5)奇妙に見えます。それは簡単にあなたの問題になる可能性があります。

ロックなしで共有グローバル変数を使用しています。ほとんどの場合は問題にならないかもしれませんが、異なるスレッドから変更可能な状態へのすべての同時アクセスを適切に同期しない限り、最終的に奇妙な失敗が発生する可能性があります。

于 2013-07-24T03:09:08.537 に答える