你知道吗?

在我的心里

你是多么的重要

就像

请允许我来一段 freestyle

你们准备好了妹油

你看

这个碗

它又大又圆

就像

这条面

它又长又宽

你们

在这里

看文章

觉得 很开心

就像

我在这里

给你们

写文章

觉得很开心

skr~~

不好意思

走错片场了

ok..

接下来,就是

学习 python 的正确姿势

咱们在上一次的

python爬虫13 | 秒爬,这多线程爬取速度也太猛了,这次就是要让你的爬虫效率杠杠的

了解了一些 python 高效爬虫的概念

比如多线程、多进程、协程等

那么我们这一篇就开始了解多线程的具体使用

在 python 中

常用的多线程的模块有这么几个

_thread

threading

Queue

之前有个 thread 模块

被 python3 抛弃了

改名为  _thread

但其实 _thread 也没什么人用

因为 _thread 有的 threading 都有

_thread 没有的 threading 依然有

那么接下来我们就先来玩玩 threading 吧

在此之前

(请允许小帅b又开始吹水了~)

介绍一下 小帅b 的一点背景

小帅b呢

平常上班时间都会去河边摸鱼

每天得摸 20 条鱼

一条一条的摸

为的是什么

为的是安抚这些鱼的心情

这样以后送到餐前的红烧鱼才更加美味

小帅b每天得摸 20 条鱼

每隔一秒钟摸一条

也就是这样

import time

def moyu_time(name, delay, counter):
 while counter:
   time.sleep(delay)
   print("%s 开始摸鱼 %s" % (name, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
   counter -= 1 if __name__ == '__main__':
 moyu_time('小帅b',1,20)

后来

小帅b知道了多线程

拍脑一想

我靠

应该把小明和小红拉过来

让他们一起帮我摸鱼啊

也就是让小明和小红同时一人摸 10 条鱼

想想就开心

在 小帅b 的威逼利诱下

他们俩不情愿的手拉着手来到了河边

小帅b看小红是女生

就让小红每摸一条鱼休息 2 秒钟

而小明每摸一条鱼休息 1 秒钟

先扔一段代码给你

# encoding = utf-8

import threading
import time # 创建一个线程子类
class MyThread(threading.Thread):
  def __init__(self,threadID, name, counter):
    threading.Thread.__init__(self)
    self.threadID = threadID
    self.name = name
    self.counter = counter   def run(self):
    print("开始线程:" + self.name)
    moyu_time(self.name, self.counter, 10)
    print("退出线程:" + self.name) def moyu_time(threadName, delay, counter):
  while counter:
    time.sleep(delay)
    print("%s 开始摸鱼 %s" % (threadName, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
    counter -= 1 # 创建新线程
# 小帅b找了两个人来摸鱼
# 让小明摸一次鱼休息1秒钟
# 让小红摸一次鱼休息2秒钟
thread1 = MyThread(1, "小明", 1)
thread2 = MyThread(2, "小红", 2) # 开启新线程
thread1.start()
thread2.start()
# 等待至线程中止
thread1.join()
thread2.join()
print ("退出主线程")

在这里呢

我们创建了一个线程类

然后继承 threading.Thread

在我们这个线程类里面定义了一个 run 方法

这个 run 方法去调用了摸鱼的方法

可以看到我们创建了两个线程

一个叫小明线程

一个叫小红线程

thread1 = MyThread(1, "小明", 1)
thread2 = MyThread(2, "小红", 2)

当我们的线程调用 start 方法的时候

它们就会去执行 run 方法

而我们用到的 join 方法呢

是为了让线程执行完

再终止主程序

运行一下就是这样

开始线程:小明
开始线程:小红
小明 开始摸鱼 2019-03-10 23:15:26
小红 开始摸鱼 2019-03-10 23:15:27
小明 开始摸鱼 2019-03-10 23:15:27
小明 开始摸鱼 2019-03-10 23:15:28
小红 开始摸鱼 2019-03-10 23:15:29
小明 开始摸鱼 2019-03-10 23:15:29
小明 开始摸鱼 2019-03-10 23:15:30
小明 开始摸鱼 2019-03-10 23:15:31
小红 开始摸鱼 2019-03-10 23:15:31
小明 开始摸鱼 2019-03-10 23:15:32
小明 开始摸鱼 2019-03-10 23:15:33
小红 开始摸鱼 2019-03-10 23:15:33
小明 开始摸鱼 2019-03-10 23:15:34
小红 开始摸鱼 2019-03-10 23:15:35
小明 开始摸鱼 2019-03-10 23:15:35
退出线程:小明
小红 开始摸鱼 2019-03-10 23:15:37
小红 开始摸鱼 2019-03-10 23:15:39
小红 开始摸鱼 2019-03-10 23:15:41
小红 开始摸鱼 2019-03-10 23:15:43
小红 开始摸鱼 2019-03-10 23:15:45
退出线程:小红
退出主线程 Process finished with exit code 0

小帅b再也不用摸鱼了

后来小明和小红都不乐意了

凭什么就我们两个摸鱼

这时候 小帅b 只能去找更多人了

连 小帅b 家的狗都叫过来了

然后

就疯狂的开启线程

thread1 = MyThread(1, "小明", 1)
thread2 = MyThread(2, "小红", 2)
thread3 = MyThread(3, "小黄", 2)
thread4 = MyThread(4, "小绿", 2)
...
thread5 = MyThread(55, "小青", 2)
thread6 = MyThread(56, "小白", 2)
thread7 = MyThread(57, "小狗", 2)

stop!!!

这可不行

因为频繁的创建线程 销毁线程

非常的浪费资源

所以呢

应该把他们放到池子里面去一起洗澡

哈,也就是

线程池

通过线程池就可以重复利用线程

不会造成过多的浪费

在 python 中

可以使用 ThreadPoolExecutor 来实现线程池

我们来往池子里塞 20 个线程

然后在循环的时候每次拿一个线程来摸鱼

def moyu_time(name, delay, counter):
  while counter:
    time.sleep(delay)
    print("%s 开始摸鱼 %s" % (name, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
    counter -= 1 if __name__ == '__main__':
  pool = ThreadPoolExecutor(20)
  for i in range(1,5):
    pool.submit(moyu_time('xiaoshuaib'+str(i),1,3))

运行一下

xiaoshuaib1 开始摸鱼 2019-03-10 23:30:10
xiaoshuaib1 开始摸鱼 2019-03-10 23:30:11
xiaoshuaib1 开始摸鱼 2019-03-10 23:30:12
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:13
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:14
xiaoshuaib2 开始摸鱼 2019-03-10 23:30:15
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:16
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:17
xiaoshuaib3 开始摸鱼 2019-03-10 23:30:18
xiaoshuaib4 开始摸鱼 2019-03-10 23:30:19
xiaoshuaib4 开始摸鱼 2019-03-10 23:30:20
xiaoshuaib4 开始摸鱼 2019-03-10 23:30:21

可以看到

我们每次从线程池里面去拿一个线程来摸鱼

这样就不会去重复的创建销毁线程了

当然

我们还可以用一个叫做 Queue 的队列来创建线程池

队列嘛~

就是可以往里塞东西

也可以往里拉东西

所以我们在使用队列的时候

最常用的方法就是 put 和 get 了

还是拿摸鱼为例

我们创建一个长度为 6 的队列

接着根据队列的长度创建了线程

每个线程都让它们处于守护状态

也就是需要的时候

马上执行

def queue_pool():
  queue = Queue(6)
  for i in range(queue.maxsize):
    t = CustomThread(queue)
    t.setDaemon(True)
    t.start()

接着我们就可以用 put 方法

把我们想做的事情往队列里面塞

比如这里我们想要摸鱼

for i in range(20):
  queue.put(moyu)
queue.join()
def moyu():
  print(" 开始摸鱼 %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))

要执行的话就需要去队列里面取了

q_method = self.__queue.get()
q_method()
self.__queue.task_done()

完整代码如下

import threadingimport timefrom queue import Queue

class CustomThread(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.__queue = queue
def run(self): while True: q_method = self.__queue.get() q_method() self.__queue.task_done()
def moyu(): print(" 开始摸鱼 %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
def queue_pool(): queue = Queue(5) for i in range(queue.maxsize): t = CustomThread(queue) t.setDaemon(True) t.start()
for i in range(20): queue.put(moyu) queue.join()
if __name__ == '__main__': queue_pool()

本篇就到这里吧

ps:本来想接着写一下用多线程来爬取网站的,篇幅有限,咱们下一篇再见

peace

点个好看啊~~(破音)

python爬虫14 | 就这么说吧,如果你不懂python多线程和线程池,那就去河边摸鱼!的更多相关文章

  1. Python多线程、线程池及实际运用

    我们在写python爬虫的过程中,对于大量数据的抓取总是希望能获得更高的速度和效率,但由于网络请求的延迟.IO的限制,单线程的运行总是不能让人满意.因此有了多线程.异步协程等技术. 下面介绍一下pyt ...

  2. Python爬虫之路——简单网页抓图升级版(添加多线程支持)

    转载自我的博客:http://www.mylonly.com/archives/1418.html 经过两个晚上的奋斗.将上一篇文章介绍的爬虫略微改进了下(Python爬虫之路--简单网页抓图),主要 ...

  3. Python 多线程和线程池

    一,前言 进程:是程序,资源集合,进程控制块组成,是最小的资源单位 特点:就对Python而言,可以实现真正的并行效果 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦 线程:是 ...

  4. python(13)多线程:线程池,threading

    python 多进程:多进程 先上代码: pool = threadpool.ThreadPool(10) #建立线程池,控制线程数量为10 reqs = threadpool.makeRequest ...

  5. Python爬虫入门教程 13-100 斗图啦表情包多线程爬取

    斗图啦表情包多线程爬取-写在前面 今天在CSDN博客,发现好多人写爬虫都在爬取一个叫做斗图啦的网站,里面很多表情包,然后瞅了瞅,各种实现方式都有,今天我给你实现一个多线程版本的.关键技术点 aioht ...

  6. python爬虫简单实现,并在java中调用python脚本,将数据保存在json文件中

    # coding:utf-8 import urllib2 from bs4 import BeautifulSoup import json import sys reload(sys) sys.s ...

  7. python DBUtils 线程池 连接 Postgresql(多线程公用线程池,DB-API : psycopg2)

    一.DBUtils DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块,DBUtils提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动 ...

  8. python-多线程和线程池

    import threading # 点击查看它的用法 传统多线程方案会使用“即时创建, 即时销毁”的策略. from multiprocessing.dummy import Pool # 线程池 ...

  9. python爬虫16 | 你,快去试试用多进程的方式重新去爬取豆瓣上的电影

    我们在之前的文章谈到了高效爬虫 在 python 中 多线程下的 GIL 锁会让多线程显得有点鸡肋 特别是在 CPU 密集型的代码下 多线程被 GIL 锁搞得效率不高 特别是对于多核的 CPU 来说 ...

随机推荐

  1. JDK部分源码阅读与理解

    本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2016/05/31/JDK部分源码阅读与理解/ 不喜欢重复造轮子,不喜欢贴各种东西.JDK ...

  2. idea2016的使用心得 --- 太棒了

    今天打开myeclipse感觉里面全是project,也懒着换地方了,因为这些代码还要时常看,索性安装了idea试试水,感觉还不错,用起来并不比myeclipse差,跟webstorm差不多,他俩就是 ...

  3. 通过adb push 从电脑里复制文件到手机里

    在开发中.我们 常常 须要 从 电脑 拷贝 一些 文件 到  自己的 app 目录里. 我之前的 方式 是 将 手机 链接 电脑,然后 从 电脑里 找到 app 文件夹,然后 进行 拷贝. 可是 这种 ...

  4. E - 吃糖

    题目描述: 某人买了n兜糖果,第i兜有Ai块糖.此人把所有这些糖果用一个数字标记起来:他这样标记这些糖,第一袋糖用用数字1到A1,第二袋糖用数字A1+1到A1+A2,如此类推.如果还没明白看样例可以更 ...

  5. Window attributes属性详解

    以下属性以Dialog为例来讲解: <item name="windowBackground"> 窗体的背景 </item><item name=&q ...

  6. bzoj 1453 双面棋盘

    题目大意: 一个黑白方格图 支持单点修改 查询黑色与白色联通快个数 思路: 可以把每一行压为一个点 使用线段树来维护 然后两行合并的时候使用并查集来合并 #include<iostream> ...

  7. 杂项:E-Learning

    ylbtech-杂项:E-Learning 1.返回顶部 1. E-Learning:英文全称为(Electronic Learning),中文译作“数字(化)学习”.“电子(化)学习”.“网络(化) ...

  8. JSP-Runoob:JSP 自动刷新

    ylbtech-JSP-Runoob:JSP 自动刷新 1.返回顶部 1. JSP 自动刷新 想象一下,如果要直播比赛的比分,或股票市场的实时状态,或当前的外汇配给,该怎么实现呢?显然,要实现这种实时 ...

  9. 使用adb进行关机(转载)

    转自:http://hi.baidu.com/fangqianshu/item/dc52b92d31b2dd1542634a3d 其实进入adb shell,然后执行reboot -p或者直接在命令行 ...

  10. 使用Keras做OCR时报错:ValueError: Tensor Tensor is not an element of this graph

    现象 项目使用 Flask + Keras + Tensorflow 同样的代码在机器A和B上都能正常运行,但在机器C上就会报如下异常.机器A和B的环境是先安装的,运行.调试成功后才尝试在C上跑. F ...