Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使程序成为多线程后,程序速度会显著降低吗?_Python_Urllib2_Python Multithreading - Fatal编程技术网

Python 使程序成为多线程后,程序速度会显著降低吗?

Python 使程序成为多线程后,程序速度会显著降低吗?,python,urllib2,python-multithreading,Python,Urllib2,Python Multithreading,如果我问这个问题时看起来像个傻瓜,那是因为这是我第一次尝试多线程。对不起 鉴于多线程是为了加快进程,我试图找出我在这方面的错误。我注意到的第一件事是,“主线程”线程比它应该的速度要慢得多(它是唯一一个不使用代理的线程) 在多线程进程之前,它将在一分钟内以单个进程/线程下载大约10-15个图像。但现在,“多线程”(这是唯一一个不通过代理发送HTTP请求的线程)实际上从未出现(如您所见:)。它应该是最快的线程 我希望我能把我的问题解释清楚 附言:在程序开始时,它会在15秒内下载大约20张图片;然而,

如果我问这个问题时看起来像个傻瓜,那是因为这是我第一次尝试多线程。对不起

鉴于多线程是为了加快进程,我试图找出我在这方面的错误。我注意到的第一件事是,“主线程”线程比它应该的速度要慢得多(它是唯一一个不使用代理的线程)

在多线程进程之前,它将在一分钟内以单个进程/线程下载大约10-15个图像。但现在,“多线程”(这是唯一一个不通过代理发送HTTP请求的线程)实际上从未出现(如您所见:)。它应该是最快的线程

我希望我能把我的问题解释清楚

附言:在程序开始时,它会在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.')
#/usr/bin/env python
导入系统
导入字符串
导入操作系统路径
导入urllib.request
导入线程
从时间导入gmtime、strftime、sleep
从随机进口选择
#我们的代理人名单
代理=[]
下载量=1
#我们要下载的文件数
target=int(sys.argv[1])
#参数2-代理
尝试:
系统argv[2]
除:
打印(“”)
其他:
param=sys.argv[2]
如果参数find('.txt')!=-1:
打印('正在加载指定的代理列表('+param+')。)
f=打开(参数“r+”)
打印('期初'+f.name)
proxylist=f.read()
f、 关闭()
#按新行拆分检索到的列表
代理=proxylist.split('\n')
其他:
打印('指定了单个代理')
proxies.append(参数)
类线程(threading.thread):
定义初始化(self、ID、name、proxy):
threading.Thread.\uuuuu init\uuuuuu(自)
self.id=id
self.name=名称
self.downloads=0
self.proxy=proxy
self.running=True
self.fails=0
def运行(自):
全球下载
如果self.proxy!=错误:
#id始终大于1,因此将id设为-1
self.proxy=代理[(self.id-1)]
打印(self.name+'使用代理启动:'+self.proxy)
#让我们的请求通过代理
self.p_handler=urllib.request.ProxyHandler({'http':self.proxy})
self.opener=urllib.request.build\u opener(self.p\u处理程序)
urllib.request.install_opener(self.opener)
其他:
打印(self.name+“无代理启动”。)
同时下载10:
打印(self.name+':代理不工作。正在停止线程。“)
self.running=False
self.fails+=1
除:
通过
其他:
打印(self.name+':下载“+filename+'…”+str(下载))
#如果self.downloads%10==0:
#打印(self.name+':睡一会儿)
#睡眠(60)
下载次数+=1
self.downloads+=1
睡眠(5)
#如果“已下载”文件夹不存在,让我们创建它
如果不是os.path.isdir(“已下载”):
尝试:
os.mkdir('已下载')
除:
通过
#线程数
线程计数=1
#创建线程,并启动它们
尝试:
线程(0,'主线程',False).start()
对于代理中的x:
线程(线程计数,'thread-'+str(线程计数),代理[(线程计数-1)])。开始()
线程计数+=1
除:
打印('无法启动线程')

我不知道实际的问题是什么,但我注意到一件事是您使用了
urllib.request.install\u opener
。这将设置一个默认的全局开启器,因此每个线程都将看到更改。很可能在第一次执行时,大多数线程都会使用分配给它们的代理,但在这之后,所有请求都会转到同一个代理,而您会被代理或其他什么限制

睡眠(5)看起来很奇怪。这很容易成为你的问题


您正在使用没有锁定的共享全局变量。在大多数情况下,它可能不会对您造成影响,但最终您可能会遇到奇怪的失败,除非您正确地同步来自不同线程的对可变状态的所有同步访问。

他正在下载URL,因此他是io绑定的。但是,通过并行进行,他应该会更快。在python中,由于Gil,多线程在CPU受限时没有帮助。@VaughnCato多线程在I/O受限时应该有帮助,而不是相反。@mr2ert:多线程如何让他在internet连接上获得更多带宽?@VaughnCato:在python中,多线程实际上往往不会帮助CPU受限的程序,因为它的。对于此类问题,建议使用。建议使用螺纹连接。它不会增加您的带宽,但如果您不能充分利用串行请求的连接,并行请求可能会更快。@VaughnCato我不是说它是。一般的经验法则是,多线程实际上会减慢CPU限制的任务(如计算素数等)。这是因为GIL。是的,但它仍然会使线休眠。你真的想这么做吗?它只有在成功下载图像后才会休眠。睡眠是否是一个问题取决于线程的数量和下载的大小。但是5秒是很多。