Python并发之threading模块
admin
2023-07-31 01:43:22
0

python并发:对线程的介绍

Python有大量不同的并发模块,例如threading,queues和multiprocessing。threading模块是实现并发的主要途径。几年前,multiprocessing模块被加到python的标准库中。但这篇文章集中讨论threading模块。

入门

我们先用一个简单例子来说明线程是如何工作的。我们创建一个Thread类的子类,并把它的名字输出到标准输出(stdout)里。让我们开始吧。

12345678910111213141516171819202122232425262728293031323334353637 import randomimport time from threading import Thread ########################################################################class MyThread(Thread):    \”\”\”    A threading example    \”\”\”     #———————————————————————-    def __init__(self, name):        \”\”\”Initialize the thread\”\”\”        Thread.__init__(self)        self.name = name        self.start()     #———————————————————————-    def run(self):        \”\”\”Run the thread\”\”\”        amount = random.randint(3, 15)        time.sleep(amount)        msg = \”%s has finished!\” % self.name        print(msg) #———————————————————————-def create_threads():    \”\”\”    Create a group of threads    \”\”\”    for i in range(5):        name = \”Thread #%s\” % (i+1)        my_thread = MyThread(name=name) if __name__ == \”__main__\”:    create_threads()

在上面的代码中,我们引入了Python的random模块,time模块并且从threading模块中引入了Thread类。接着创建一个Thread类的子类,并重写它的__init__方法,让其接收一个名为name的参数。为了开启一个线程,你必须调用它的start()方法,所以我们在init方法最后调用它。当你开启一个线程时,它会自动调用run()方法。我们重写了它的run方法,让它选择一个随机时间数去休眠。例子中的random.randint让python随机选择3到15之间的一个数,然后我们让线程休眠这么多秒来模拟线程在做一些事情。最后我们将线程名称打印出来让用户知道线程已经完成。

create_threads方法创建了5个线程,分别给了独一无二的名称。如果你运行这段代码,你将看到类似如下的结果:

12345 Thread #2 has finished!Thread #1 has finished!Thread #3 has finished!Thread #4 has finished!Thread #5 has finished!

每次输出的顺序都会不同。试着运行几次代码观察顺序的变化。

写一个多线程的下载器

相对之前的例子,一个工具程序能更好地解释线程是如何工作的。所以在这个例子中,我们创建了一个可以从网上下载文件的Thread类。美国国税局有大量给美国公民用来记税的PDF表单。我们用这个免费的资源来举例,代码如下:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 # Use this version for Python 2import osimport urllib2 from threading import Thread ########################################################################class DownloadThread(Thread):    \”\”\”    A threading example that can download a file    \”\”\”     #———————————————————————-    def __init__(self, url, name):        \”\”\”Initialize the thread\”\”\”        Thread.__init__(self)        self.name = name        self.url = url     #———————————————————————-    def run(self):        \”\”\”Run the thread\”\”\”        handle = urllib2.urlopen(self.url)        fname = os.path.basename(self.url)        with open(fname, \”wb\”) as f_handler:            while True:                chunk = handle.read(1024)                if not chunk:                    break                f_handler.write(chunk)        msg = \”%s has finished downloading %s!\” % (self.name,                                                   self.url)        print(msg) #———————————————————————-def main(urls):    \”\”\”    Run the program    \”\”\”    for item, url in enumerate(urls):        name = \”Thread %s\” % (item+1)        thread = DownloadThread(url, name)        thread.start() if __name__ == \”__main__\”:    urls = [\”http://www.irs.gov/pub/irs-pdf/f1040.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040a.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040ez.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040es.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040sb.pdf\”]    main(urls)

这基本上是对第一版的完全重写。在这个例子中,我们引用了os、urllib2和threading模块。我们在thread类里使用urllib2模块来下载文件。使用os模块提取下载文件的文件名,这样我们可以在自己电脑上创建同名文件。在DownloadThread类中,我们让__init__接收一个url和一个线程名。在run方法中,我们访问url,抽取文件名,并使用该文件名在磁盘上命名或创建一个文件。然后我们使用while循环以每次1KB的速度下载文件并把它写进磁盘。一旦文件完成保存,我们打印出线程的名称和完成下载的url。

升级

这个代码的Python3版本略微有些不同。你必须引用urllib,并使用urllib.request.urlopen代替urllib2urlopen。这是python3的代码:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 # Use this version for Python 3import osimport urllib.request from threading import Thread ########################################################################class DownloadThread(Thread):    \”\”\”    A threading example that can download a file    \”\”\”     #———————————————————————-    def __init__(self, url, name):        \”\”\”Initialize the thread\”\”\”        Thread.__init__(self)        self.name = name        self.url = url     #———————————————————————-    def run(self):        \”\”\”Run the thread\”\”\”        handle = urllib.request.urlopen(self.url)        fname = os.path.basename(self.url)        with open(fname, \”wb\”) as f_handler:            while True:                chunk = handle.read(1024)                if not chunk:                    break                f_handler.write(chunk)        msg = \”%s has finished downloading %s!\” % (self.name,                                                   self.url)        print(msg) #———————————————————————-def main(urls):    \”\”\”    Run the program    \”\”\”    for item, url in enumerate(urls):        name = \”Thread %s\” % (item+1)        thread = DownloadThread(url, name)        thread.start() if __name__ == \”__main__\”:    urls = [\”http://www.irs.gov/pub/irs-pdf/f1040.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040a.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040ez.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040es.pdf\”,            \”http://www.irs.gov/pub/irs-pdf/f1040sb.pdf\”]    main(urls)

结语

现在你从理论和实践上了解了如何使用线程。当你创建用户界面并想保持界面的可用性时,线程就特别有用。没有线程,用户界面将变得迟钝,当你下载一个大文件或者执行一个庞大的数据库查询命令时用户界面会长时间无响应。为了防止这样情况发生,你可以使用多线程来处理运行时间长的进程并且在完成后返回界面进行交互。

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...