现在我正在研究如何尽快从网站上获取数据。为了获得更快的速度,我考虑使用多线程。下面是我用来测试多线程和简单post之间区别的代码。
import threading
import time
import urllib
import urllib2
class Post:
def __init__(self, website, data, mode):
self.website = website
self.data = data
#mode is either "Simple"(Simple POST) or "Multiple"(Multi-thread POST)
self.mode = mode
def post(self):
#post data
req = urllib2.Request(self.website)
open_url = urllib2.urlopen(req, self.data)
if self.mode == "Multiple":
time.sleep(0.001)
#read HTMLData
HTMLData = open_url.read()
print "OK"
if __name__ == "__main__":
current_post = Post("http://forum.xda-developers.com/login.php", "vb_login_username=test&vb_login_password&securitytoken=guest&do=login", \
"Simple")
#save the time before post data
origin_time = time.time()
if(current_post.mode == "Multiple"):
#multithreading POST
for i in range(0, 10):
thread = threading.Thread(target = current_post.post)
thread.start()
thread.join()
#calculate the time interval
time_interval = time.time() - origin_time
print time_interval
if(current_post.mode == "Simple"):
#simple POST
for i in range(0, 10):
current_post.post()
#calculate the time interval
time_interval = time.time() - origin_time
print time_interval
正如您所看到的,这是一个非常简单的代码。首先,我将模式设置为“简单”,然后可以得到时间间隔:50s(可能我的速度有点慢:)。然后将模式设置为“Multiple”,得到时间间隔:35。从这我可以看出,多线程实际上可以提高速度,但结果不如我想象的好。我想要更快的速度。
通过调试,我发现程序主要阻塞在:open_url = urllib2.urlopen(req, self.data)
行,这行代码需要大量时间从指定的网站发布和接收数据。我想我可以通过添加time.sleep()
并在urlopen
函数中使用多线程来获得更快的速度,但是我不能这样做,因为它是python自己的函数。
如果不考虑服务器阻塞post速度的不合理限制,我还能做什么来获得更快的速度?或者其他我可以修改的代码?太多了!
在许多情况下,python的线程并不能很好地提高执行速度。。。有时候,这会让事情变得更糟。有关详细信息,请参见David Beazley's PyCon2010 presentation on the Global Interpreter Lock/Pycon2010 GIL slides。这个演示内容非常丰富,我强烈推荐给任何考虑线程的人。。。
尽管David Beazley的演讲解释了网络流量改善了Python线程模块的调度,但是您应该使用multiprocessing module。我在你的代码中加入了这个选项(见我的答案的底部)。
在我的一台旧机器上运行(Python2.6.6):
我同意TokenMacGuy的评论,上面的数字包括将
.join()
移动到不同的循环。如您所见,python的多处理速度明显快于线程。你做错的最大一件事,也就是最伤你的吞吐量,就是你调用
thread.start()
和thread.join()
的方式:每次通过循环,您都会创建一个线程,启动它,然后等待它完成,然后再转到下一个线程。你一点也不做!
你应该做的是:
请记住,在Python中,多线程可以“提高速度”的唯一情况是当您有像这样的操作时会受到严重的I/O限制。否则多线程不会提高“速度”,因为它不能在多个CPU上运行(不,即使您有多个内核,python也不会这样工作)。当您希望两件事同时完成时,应该使用多线程,而不是当您希望两件事并行时(即两个进程分别运行)。
现在,你实际上所做的并不会增加任何一个DNS查找的速度,但是它允许在等待其他一些结果的同时发送多个请求,但是你应该小心你做了多少,否则你只会使响应时间比现在更糟。
另外,请停止使用urllib2,并使用请求:http://docs.python-requests.org
相关问题 更多 >
编程相关推荐