当前位置: 首页 > 面试题库 >

在python中使用多线程时如何获得更快的速度

阙阳夏
2023-03-14
问题内容

现在我正在研究如何尽快从网站获取数据。为了获得更快的速度,即时通讯正在考虑使用多线程。这是我用来测试多线程和简单文章之间差异的代码。

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

如您所见,这是一个非常简单的代码。首先,我将模式设置为“ Simple”,然后我可以得到时间间隔: 50s
(也许我的速度有点慢:()。然后我将模式设置为“ Multiple”,然后我得到了时间间隔: 35
。从我可以看到,多线程实际上可以提高速度,但是结果却不像我想象的那样好,我想获得更快的速度。

从调试中,我发现该程序主要在以下行阻塞:open_url = urllib2.urlopen(req, self.data),此行代码需要大量时间来发布和接收来自指定网站的数据。我想也许我可以通过time.sleep()urlopen函数内部添加和使用多线程来获得更快的速度,但是我不能这样做,因为它是python自己的函数。

如果不考虑服务器阻止发布速度的可能限制,我还可以做些什么来获得更快的速度?或我可以修改的任何其他代码?多谢!


问题答案:

在许多情况下,python的线程无法很好地提高执行速度…有时,它会使情况变得更糟。有关更多信息,请参阅全球解释器锁/ Pycon2010
GIL幻灯片
上David
Beazley的PyCon2010演示。该演示非常有用,我强烈推荐给任何考虑线程的人…

即使David
Beazley的演讲解释了网络流量可以改善Python线程模块的调度,您仍应使用multiprocessing模块。我将此作为选项包含在您的代码中(请参见答案底部)。

在我的一台旧机器上运行此命令(Python 2.6.6):

current_post.mode == "Process"  (multiprocessing)  --> 0.2609 seconds
current_post.mode == "Multiple" (threading)        --> 0.3947 seconds
current_post.mode == "Simple"   (serial execution) --> 1.650 seconds

我同意TokenMacGuy的评论,上面的数字包括将.join()移到另一个循环。如您所见,python的多处理比线程处理快得多。

from multiprocessing import Process
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)
        #   "Multiple"    (Multi-thread POST)
        #   "Process"     (Multiprocessing)
        self.mode = mode
        self.run_job()

    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"

    def run_job(self):
        """This was refactored from the OP's code"""
        origin_time = time.time()
        if(self.mode == "Multiple"):

            #multithreading POST
            threads = list()
            for i in range(0, 10):
               thread = threading.Thread(target = self.post)
               thread.start()
               threads.append(thread)
            for thread in threads:
               thread.join()
            #calculate the time interval
            time_interval = time.time() - origin_time
            print "mode - {0}: {1}".format(method, time_interval)

        if(self.mode == "Process"):

            #multiprocessing POST
            processes = list()
            for i in range(0, 10):
               process = Process(target=self.post)
               process.start()
               processes.append(process)
            for process in processes:
               process.join()
            #calculate the time interval
            time_interval = time.time() - origin_time
            print "mode - {0}: {1}".format(method, time_interval)

        if(self.mode == "Simple"):

            #simple POST
            for i in range(0, 10):
                self.post()
            #calculate the time interval
            time_interval = time.time() - origin_time
            print "mode - {0}: {1}".format(method, time_interval)
        return time_interval

if __name__ == "__main__":

    for method in ["Process", "Multiple", "Simple"]:
        Post("http://forum.xda-developers.com/login.php", 
            "vb_login_username=test&vb_login_password&securitytoken=guest&do=login",
            method
            )


 类似资料:
  • 本文向大家介绍Python实现快速多线程ping的方法,包括了Python实现快速多线程ping的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Python实现快速多线程ping的方法。分享给大家供大家参考。具体如下: 执行结果: administrator@nagios:/win/pexpect$ ./ping.py [2011-04-25 21:30:22.126981] 192

  • 问题内容: 我试图了解Python中的线程。我看过文档和示例,但坦率地说,许多示例过于复杂,我难以理解它们。 你如何清楚地显示为多线程而划分的任务? 问题答案: 我将在下面进行总结-最终仅是几行代码: 这是以下内容的多线程版本: 描述 Map是一个很棒的小功能,是轻松将并行性注入Python代码的关键。对于那些不熟悉的人来说,地图是从Lisp等功能语言中提炼出来的。它是将另一个功能映射到序列上的功

  • 问题内容: 在研究这个问题时,我遇到了一个使用的可能想法,但是我无法正确了解如何与线程交互。 假设我有一个给定的多线程主进程,并且我想附加到其中的特定线程(可能来自派生的子进程)。 我可以附加到特定线程吗?(有关此问题的手册有所不同。) 如果是这样,是否意味着单步执行仅一步步执行该线程的指令?它会停止所有进程的线程吗? 如果是这样,在我调用或时,其他所有线程是否仍保持停止状态?还是 所有 线程都继

  • 本文向大家介绍python多线程编程中的join函数使用心得,包括了python多线程编程中的join函数使用心得的使用技巧和注意事项,需要的朋友参考一下 今天去辛集买箱包,下午挺晚才回来,又是恶心又是头痛。恶心是因为早上吃坏东西+晕车+回来时看到车祸现场,头痛大概是烈日和空调混合刺激而成。没有时间没有精神没有力气学习了,这篇博客就说说python中一个小小函数。 由于坑爹的学校坑爷的专业,多线程

  • 我是Java新手。在发布这个问题之前,我已经搜索了这个网站。如果我的问题看起来很愚蠢,请原谅我。 下面给出了我正在寻找答案的代码。 我打算让4名选手参加100米赛跑。主线程以最高优先级运行,因此它可以检查每个玩家的进度。我在主线程和子线程中都编写了Yield方法,认为主线程和子线程都将获得相当多的CPU时间。 该程序为每次运行产生以下三种不同的输出。 > 它产生"Gun is Fired"消息,之

  • 问题内容: 我在某个字段上有一个带有getter 和setter 的类,例如field 说一个类的对象。 在这里synchronized– 不是。 我正在从多个线程中更新值。每个线程都在获取值,并进行适当设置。线程不会以任何方式共享任何其他资源。 在每个线程中执行的代码如下。 该方法只是对通过传递给它的参数从构造函数内部更新的成员调用上述方法: 当我按较大的顺序运行此线程时,线程之间的交错并不多-