那是您没用好而已,为何Python为那样慢

Python语言 近年来 人气爆棚 。它布满应用于互联网支出运转,数据正确,网络开拓,以及网络安全主题素材中。

壹、            Python重要应用领域

编写翻译型与解释型。

GIL 是什么东西

先注明下 GIL 其实并不是 Python 语言的特色,它实际是在落成 Python
解释器(CPython)时所引进的二个概念。

那么,CPython 又是怎么样啊? 类比
C++,那是壹套语言的正儿八经,可是能够再分歧的编译器上来编译成可实践代码。相比较著名的编写翻译器比方GCC, Visual C++等。Python 也同样,一样的代码能够通过
CPython、PyPy、Psyco、JPython等不等的 Python 意况来实行。例如 JPython
就从未有过 GIL。

因为 CPython 是大繁多环境下私下认可的 Python
施行情形,所以众多人在概念上就暗中同意 CPython 正是 Python,也就想当然的把
GIL 作为了 Python 语言的短处。所以自身那里再度强烈一点: GIL 并不是 Python
的天性, Python 完全能够不依据于 GIL。

这正是说 CPython 中的 GIL 又是什么样吧?

全称是 Global Interpreter Lock。

官方网站是那样解释的:

一个防止多线程并发执行机器码的一个 Mutex。

尼玛啊,这不正是3个 Bug 般存在的大局锁嘛!表急。。。

然而, Python 在进程上完全未有优势可言。

(1)       云计算

  编译器是把源程序的每一条语句都编写翻译成机器语言,并保留成二进制文件,那样运维时计算机能够间接以机器语言来运维此程序,速度高速; 

真是 Bug ?

玩过 Python 的,小编深信不疑广大都在操心 GIL
在潜移默化10二线程程序的施行品质。但,小编此番想说你顾忌的未免太多了。

那并不是 Python 中的 Bug
,它的存在只然则消除了一部分主题素材,并无法减轻全体的标题。毕竟人都无完人。

在速度上,Java怎么着同C,C++,C#可能Python相相比较?答案大致全盘取决于要运转的行使。在那些难点上,未有健全的评判标准,可是The
Computer Language Benchmarks Game 是三个没有错的点子。

(2)       WEB开发

  而解释器则是只在实行顺序时,才一条一条的分解成机器语言给Computer来实行,所以运营速度是不及编写翻译后的程序运营的快的.

那正是说,大家应有怎么合理的行使 GIL 呢?

在批评普通的GIL从前,有好几要重申的是GIL只会影响到那么些严重依赖CPU的程序(比如计算型的)。
假设您的顺序半数以上只会涉及到I/O,比方互联网互动,那么使用二十多线程就很体面,
因为它们大部分时间都在等候。实际上,你一点一滴能够放心的开创几千个Python线程,
当代操作系统运转这么八线程未有别的压力,没啥可顾虑的。

而对于凭仗CPU的顺序,你必要弄清楚推行的持筹握算的性状。
举例,优化底层算法要比接纳二10102线程运营快得多。
类似的,由于Python是分解实践的,尽管你将这几性格能瓶颈代码移到3个C语言扩大模块中,
速度也会提高的相当的慢。假若您要操作数组,那么使用NumPy那样的扩张会尤其的全速。
最终,你还足以考虑下其余可选达成方案,比方PyPy,它通过1个JIT编写翻译器来优化实行效用(可是在写那本书的时候它还不能帮衬Python 三)。

再有某个要专注的是,线程不是专程用来优化品质的。
3个CPU正视型程序恐怕会使用线程来治本三个图形用户分界面、贰个互联网连接或任何服务。
这时候,GIL会生出局部标题,因为假设1个线程长时间具备GIL的话会促成别的非CPU型线程一向等待。
事实上,叁个写的不得了的C语言扩充会导致那些难题更为严重,
尽管代码的测算部分会比从前运营的更加快些。

说了如此多,未来想说的是大家有二种政策来化解GIL的欠缺。
首先,如果你完全职业于Python景况中,你可以应用 multiprocessing
模块来创设三个进程池,
并像壹只管理器一样的采取它。举例,倘诺你有如下的线程代码:

# Performs a large calculation (CPU bound)
def some_work(args):
    ...
    return result

# A thread that calls the above function
def some_thread():
    while True:
        ...
        r = some_work(args)
    ...

修改代码,使用进度池:

# Processing pool (see below for initiazation)
pool = None

# Performs a large calculation (CPU bound)
def some_work(args):
    ...
    return result

# A thread that calls the above function
def some_thread():
    while True:
        ...
        r = pool.apply(some_work, (args))
        ...

# Initiaze the pool
if __name__ == '__main__':
    import multiprocessing
    pool = multiprocessing.Pool()

其1通过行使一个才干运用进度池化解了GIL的难题。
当二个线程想要实施CPU密集型专门的学问时,会将任务发给进度池。
然后进度池会在其余二个进度中运维八个单身的Python解释器来行事。
当线程等待结果的时候会释放GIL。
并且,由于计算任务在独立解释器中实行,那么就不会受限于GIL了。
在二个多核系统方面,你会发觉那几个手艺能够让你很好的行使多CPU的优势。

除此以外三个化解GIL的国策是运用C扩大编制程序才具。
首要思虑是将总计密集型职务转移给C,跟Python独立,在劳作的时候在C代码中释放GIL。
那足以经过在C代码中插入上面那样的十分宏来落成:

#include "Python.h"
...

PyObject *pyfunc(PyObject *self, PyObject *args) {
   ...
   Py_BEGIN_ALLOW_THREADS
   // Threaded C code
   ...
   Py_END_ALLOW_THREADS
   ...
}

一经您使用别的工具访问C语言,举个例子对于Cython的ctypes库,你不须求做任何事。
比如,ctypes在调用C时会自动释放GIL。

链接:

(叁)       科学计算、人工智能

  动态语言和静态语言
  日常大家所说的动态语言、静态语言是指动态类型语言和静态类型语言。

讨论

洋洋技术员在面对线程品质难题的时候,立即就会怪罪GIL,什么皆以它的主题素材。
其实那样子太不厚道也太天真了点。
作为一个忠实的例证,在八线程的互连网编制程序中潜在的 stalls
恐怕是因为其余原因比方2个DNS查找延时,而跟GIL毫毫无干系系。
最终你确实需求先去搞懂你的代码是还是不是确实被GIL影响到。
同时还要精通GIL超越四分之2都应当只关心CPU的管理而不是I/O.

只要您计划利用二个甩卖器池,注意的是这样做涉嫌到多少连串化和在差别Python解释器通讯。
被实行的操作需求放在2个由此def语句定义的Python函数中,不能是lambda、闭包可调用实例等,
并且函数参数和再次回到值必须要合作pickle。
同样,要实践的任务量必须丰硕大以弥补额外的通讯支出。

其它一个难点是当混合使用线程和进度池的时候会让你很脑瓜疼。
借使你要同时接纳两者,最棒在先后运行时,创建任何线程在此之前先成立一个单例的进度池。
然后线程使用一样的长本溪来拓展它们的持筹握算密集型职业。

C扩张最根本的表征是它们和Python解释器是涵养独立的。
也正是说,如若您准备将Python中的任务分配到C中去试行,
你需求保障C代码的操作跟Python保持单身,
那就象征不要接纳Python数据结构以及不要调用Python的C API。
其它2个就是您要力保C扩张所做的职业是拾足的,值得你这么做。
也正是说C扩张担当起了大气的测算任务,而不是少数多少个总括。

这几个化解GIL的方案并无法适用于具备题目。
举例,某个种类的应用程序若是被解释为多个经过管理的话并不能够很好的行事,
也不可能将它的有的代码改成C语言实施。
对于那些应用程序,你就要和谐须要解决方案了
(举例多进度访问共享内部存款和储蓄器区,多解析器运维于同3个经过等)。
只怕,你还可以够设想下其余的解释器达成,比方PyPy。

(四)       系统运营

   (一)动态类型语言:动态类型语言是指在运维时期才去做数据类型检查的言语,相当于说,在用动态类型的语言编制程序时,长久也不用给别的变量内定数据类型,该语言会在您首先次赋值给变量时,在里边将数据类型记录下来。Python和Ruby正是1种标准的动态类型语言,别的的各个脚本语言如VBScript也稍微属于动态类型语言。

依附自己对The 计算机 Language Benchmarks
Game领先10年的观望,相比较于Java,C#,Go,JavaScript,
C++等,Python是最慢的语言之壹。在那之中包罗了 JIT (C#, Java) 和 AOT
(C, C++)编译器,以及解释型语言,比如JavaScript。

(5)       金融

    (二)静态类型语言:静态类型语言与动态类型语言恰恰相反,它的数据类型是在编写翻译其间检查的,也正是说在写程序时要注脚全部变量的数据类型,C/C++是静态类型语言的卓越代表,别的的静态类型语言还有C#、JAVA等。

动态编写翻译:

(6)       图形GUI

  强类型定义语言和弱类型定义语言

二、            Python在部分小卖部的利用

    (1)强类型定义语言:强制数据类型定义的语言。也正是说,壹旦3个变量被内定了有个别数据类型,要是不通过强制调换,那么它就永恒是以此数据类型了。比方:要是您定义了3个整型变量a,那么程序根本不容许将a当作字符串类型管理。强类型定义语言是项目安全的言语。

静态编写翻译:

(1)       谷歌

    (二)弱类型定义语言:数据类型可以被忽略的言语。它与强类型定义语言相反,
一个变量能够赋不一致数据类型的值。

(2)       CIA

强类型定义语言在进程上或许略逊色于弱类型定义语言,然而强类型定义语言带来的严厉性能够使得的防止过多谬误。其它,“这门语言是还是不是动态语言”与“那门语言是或不是类型安全”之间是截然未有调换的!
  举个例子:Python是动态语言,是强类型定义语言(类型安全的语言);
VBScript是动态语言,是弱类型定义语言(类型不安全的语言);
JAVA是静态语言,是强类型定义语言(类型安全的言语)。

澳门葡京备用网址 ,瞩目:当自家关系“Python”时,小编指的是CPython那么些官方的解释器。作者也将要本文中谈到别的的解释器。

(3)       NASA

  通过上边这个介绍,我们能够汲取,python是一门动态解释性的强类型定义语言。

本身想要回答那样1个主题材料:当运转同2个主次时,为何Python会
比任何语言慢贰到拾倍?为啥大家无能为力将它变得更加快?

(4)       YouTube

  python的利害。

  先看亮点

  1. Python的永世是“优雅”、“明确”、“不难”,所以Python程序看上去总是轻巧易懂,初学者学Python,不但入门轻松,而且今后深入下去,能够编写那么些可怜万分复杂的顺序。
  2. 付出效用越来越高,Python有不行强劲的第叁方库,基本上你想经过Computer完毕任何意义,Python官方Curry都有相应的模块实行辅助,间接下载调用后,在基础库的根底上再进行开垦,大大下降开拓周期,防止再一次造轮子。
  3. 高端语言————当你用Python语言编写程序的时候,你无需思索诸如哪些处理你的先后行使的内部存款和储蓄器1类的底部细节
  4. 可移植性————由于它的开源本质,Python已经被移植在无数平台上(经过改动使它可以工作在分裂平台上)。假如您小心地防止采纳正视于系统的特征,那么你的具备Python程序无需修改就差了一点能够在市镇上享有的系统平台上运转
  5. 可扩大性————假设您须求您的1段主要代码运转得越来越快或然希望有些算法不明白,你可以把你的有的程序用C或C++编写,然后在您的Python程序中选取它们。
  6. 可嵌入性————你能够把Python嵌入你的C/C++程序,从而向您的顺序用户提供脚本功效。

  再看缺点:

  1. 速度慢,Python
    的运行速度比较C语言确实慢诸多,跟JAVA比较也要慢一些,因而那也是多多益善所谓的大牌不屑于使用Python的重要性原因,但其实那里所指的运营速度慢在大许多景观下用户是不能直接感知到的,必须依附测试工具才能反映出来,举个例子你用C运1个程序花了0.0一s,用Python是0.1s,那样C语言直接比Python快了十倍,算是非凡夸张了,可是你是不能间接通过肉眼感知的,因为三个常人所能感知的年月一点都不大单位是0.一五-0.四s左右,哈哈。其实在大繁多气象下Python已经完全能够满意你对先后速度的渴求,除非你要写对速度需求非常高的探索引擎等,这种场馆下,当然依旧建议你用C去得以落成的。
  2. 代码不能加密,因为PYTHON是解释性语言,它的源码都以以名文情势存放的,可是自个儿不以为那到底多个欠缺,假诺您的项目须要源代码必须是加密的,那您一同头就不应当用Python来去贯彻。
  3. 线程不能采纳多CPU难题,那是Python被人非议最多的几个欠缺,GIL即全局解释器锁(Global
    Interpreter
    Lock),是计算机程序设计语言解释器用于同步线程的工具,使得任几时刻仅有贰个线程在推行,Python的线程是操作系统的原生线程。在Linux上为pthread,在Windows上为Win
    thread,完全由操作系统调整线程的试行。3个python解释器进度内有一条主线程,以及多条用户程序的实践线程。即便在多核CPU平台上,由于GIL的存在,所以禁止八线程的并行实施。关于这些标题标妥洽化解办法,大家在今后线程和经过章节里再展开详尽探究。

  当大家编辑Python代码时,大家得到的是2个包涵Python代码的以.py为扩张名的文件文件。要运转代码,就供给Python解释器去奉行.py文件。

  由于整个Python语言从业内到解释器都是开源的,所以理论上,只要水平够高,任何人都得以编写制定Python解释器来举行Python代码(当然难度相当大)。事实上,确实存在四种Python解释器。

以下是最重要的因由:

(5)       Dropbox

  python的种类。

  CPython

    当大家从Python官网下载并设置好Python
三.陆后,大家就径直拿走了一个官方版本的解释器:CPython。这么些解释器是用C语言开采的,所以叫CPython。在指令行下运转python正是开发银行CPython解释器。

    CPython是利用最广的Python解释器。教程的享有代码也都在CPython下试行。

  IPython

    IPython是依据CPython之上的二个交互式解释器,相当于说,IPython只是在交互格局上装有增进,不过实践Python代码的功力和CPython是一心平等的。好比很多进口浏览器就算外观不一样,但基本其实都以调用了IE。

    CPython用>>>用作提醒符,而IPython用In [``序号``]:用作提醒符。

  PyPy

    PyPy是另三个Python解释器,它的对象是举办进程。PyPy采取JIT技术,对Python代码实行动态编译(注意不是解释),所以可以显著压实Python代码的进行进度。

    绝大多数Python代码都得以在PyPy下运维,然则PyPy和CPython有一部分是例外的,那就导致同样的Python代码在二种解释器下执行或许会有两样的结果。如若你的代码要松手PyPy下实行,就要求驾驭PyPy和CPython的分歧点。

  Jython

    Jython是运作在Java平台上的Python解释器,能够直接把Python代码编译成Java字节码试行。

  IronPython

    IronPython和Jython类似,只不过IronPython是运作在微软.Net平台上的Python解释器,能够直接把Python代码编写翻译成.Net的字节码。

Python的解释器繁多,但利用最广大的依旧CPython。就算要和Java或.Net平台相互,最佳的方法不是用Jython或IronPython,而是经过互连网调用来交互,确定保障各程序之间的独立性。

  • “它是GIL(Global Interpreter Lock全局解释器锁)”
  • “它是解释型语言而非编写翻译语言”
  • “它是动态类型语言”

(6)       Instagram

   内容编码。

    python2解释器在加载 .py
文件中的代码时,会对故事情节张开编码(暗中同意ascill),而python三对剧情开始展览编码的默以为utf-八。

    ASCII(American Standard Code for Information
Interchange,美利坚合众国标准音信置换代码)是依据拉丁字母的1套计算机编码系统,首要用来展示今世匈牙利(Hungary)语和其余西欧语言,其最四只可以用
八 位来表示(一个字节),即:贰**8 = 256,所以,ASCII码最四只可以表示 二伍15个标识。

Bin(二进制)
Oct(八进制)
Dec(十进制)
Hex(十六进制)
缩写/字符
解释
0000 0000
0
0
00
NUL(null)
空字符
0000 0001
1
1
01
SOH(start of headline)
标题开始
0000 0010
2
2
02
STX (start of text)
正文开始
0000 0011
3
3
03
ETX (end of text)
正文结束
0000 0100
4
4
04
EOT (end of transmission)
传输结束
0000 0101
5
5
05
ENQ (enquiry)
请求
0000 0110
6
6
06
ACK (acknowledge)
收到通知
0000 0111
7
7
07
BEL (bell)
响铃
0000 1000
10
8
08
BS (backspace)
退格
0000 1001
11
9
09
HT (horizontal tab)
水平制表符
0000 1010
12
10
0A
LF (NL line feed, new line)
换行键
0000 1011
13
11
0B
VT (vertical tab)
垂直制表符
0000 1100
14
12
0C
FF (NP form feed, new page)
换页键
0000 1101
15
13
0D
CR (carriage return)
回车键
0000 1110
16
14
0E
SO (shift out)
不用切换
0000 1111
17
15
0F
SI (shift in)
启用切换
0001 0000
20
16
10
DLE (data link escape)
数据链路转义
0001 0001
21
17
11
DC1 (device control 1)
设备控制1
0001 0010
22
18
12
DC2 (device control 2)
设备控制2
0001 0011
23
19
13
DC3 (device control 3)
设备控制3
0001 0100
24
20
14
DC4 (device control 4)
设备控制4
0001 0101
25
21
15
NAK (negative acknowledge)
拒绝接收
0001 0110
26
22
16
SYN (synchronous idle)
同步空闲
0001 0111
27
23
17
ETB (end of trans. block)
结束传输块
0001 1000
30
24
18
CAN (cancel)
取消
0001 1001
31
25
19
EM (end of medium)
媒介结束
0001 1010
32
26
1A
SUB (substitute)
代替
0001 1011
33
27
1B
ESC (escape)
换码(溢出)
0001 1100
34
28
1C
FS (file separator)
文件分隔符
0001 1101
35
29
1D
GS (group separator)
分组符
0001 1110
36
30
1E
RS (record separator)
记录分隔符
0001 1111
37
31
1F
US (unit separator)
单元分隔符
0010 0000
40
32
20
(space)
空格
0010 0001
41
33
21
!
叹号
0010 0010
42
34
22
"
双引号
0010 0011
43
35
23
#
井号
0010 0100
44
36
24
$
美元符
0010 0101
45
37
25
%
百分号
0010 0110
46
38
26
&
和号
0010 0111
47
39
27
闭单引号
0010 1000
50
40
28
(
开括号
0010 1001
51
41
29
)
闭括号
0010 1010
52
42
2A
*
星号
0010 1011
53
43
2B
+
加号
0010 1100
54
44
2C
,
逗号
0010 1101
55
45
2D
减号/破折号
0010 1110
56
46
2E
.
句号
00101111
57
47
2F
/
斜杠
00110000
60
48
30
0
数字0
00110001
61
49
31
1
数字1
00110010
62
50
32
2
数字2
00110011
63
51
33
3
数字3
00110100
64
52
34
4
数字4
00110101
65
53
35
5
数字5
00110110
66
54
36
6
数字6
00110111
67
55
37
7
数字7
00111000
70
56
38
8
数字8
00111001
71
57
39
9
数字9
00111010
72
58
3A
:
冒号
00111011
73
59
3B
;
分号
00111100
74
60
3C
<
小于
00111101
75
61
3D
=
等号
00111110
76
62
3E
>
大于
00111111
77
63
3F
?
问号
01000000
100
64
40
@
电子邮件符号
01000001
101
65
41
A
大写字母A 
01000010
102
66
42
B
大写字母B
01000011
103
67
43
C
大写字母C
01000100
104
68
44
D
大写字母D
01000101
105
69
45
E
大写字母E
01000110
106
70
46
F
大写字母F
01000111
107
71
47
G
大写字母G
01001000
110
72
48
H
大写字母H
01001001
111
73
49
I
大写字母I
01001010
112
74
4A
J
大写字母J
01001011
113
75
4B
K
大写字母K
01001100
114
76
4C
L
大写字母L
01001101
115
77
4D
M
大写字母M
01001110
116
78
4E
N
大写字母N
01001111
117
79
4F
O
大写字母O
01010000
120
80
50
P
大写字母P
01010001
121
81
51
Q
大写字母Q
01010010
122
82
52
R
大写字母R
01010011
123
83
53
S
大写字母S
01010100
124
84
54
T
大写字母T
01010101
125
85
55
U
大写字母U
01010110
126
86
56
V
大写字母V
01010111
127
87
57
W
大写字母W
01011000
130
88
58
X
大写字母X
01011001
131
89
59
Y
大写字母Y
01011010
132
90
5A
Z
大写字母Z
01011011
133
91
5B
[
开方括号
01011100
134
92
5C
\
反斜杠
01011101
135
93
5D
]
闭方括号
01011110
136
94
5E
^
脱字符
01011111
137
95
5F
_
下划线
01100000
140
96
60
`
开单引号
01100001
141
97
61
a
小写字母a 
01100010
142
98
62
b
小写字母b
01100011
143
99
63
c
小写字母c
01100100
144
100
64
d
小写字母d
01100101
145
101
65
e
小写字母e
01100110
146
102
66
f
小写字母f
01100111
147
103
67
g
小写字母g
01101000
150
104
68
h
小写字母h
01101001
151
105
69
i
小写字母i
01101010
152
106
6A
j
小写字母j
01101011
153
107
6B
k
小写字母k
01101100
154
108
6C
l
小写字母l
01101101
155
109
6D
m
小写字母m
01101110
156
110
6E
n
小写字母n
01101111
157
111
6F
o
小写字母o
01110000
160
112
70
p
小写字母p
01110001
161
113
71
q
小写字母q
01110010
162
114
72
r
小写字母r
01110011
163
115
73
s
小写字母s
01110100
164
116
74
t
小写字母t
01110101
165
117
75
u
小写字母u
01110110
166
118
76
v
小写字母v
01110111
167
119
77
w
小写字母w
01111000
170
120
78
x
小写字母x
01111001
171
121
79
y
小写字母y
01111010
172
122
7A
z
小写字母z
01111011
173
123
7B
{
开花括号
01111100
174
124
7C
|
垂线
01111101
175
125
7D
}
闭花括号
01111110
176
126
7E
~
波浪号
01111111
177
127
7F
DEL (delete)
删除

 

    显明ASCII码不可能将世界上的各类文字和符号全体意味着,所以,就供给新出一种能够代表享有字符和标识的编码,即:Unicode

    Unicode(统壹码、万国码、单1码)是1种在微型计算机上行使的字符编码。Unicode
是为了消除古板的字符编码方案的受制而发出的,它为各样语言中的每一种字符设定了合并并且唯1的2进制编码,规定虽有的字符和标识最少由
1陆 位来代表(三个字节),即:二 **16 = 65536,
    注:此处说的的是最少三个字节,大概越多

    UTF-捌,是对Unicode编码的削减和优化,他不再动用最少使用三个字节,而是将有所的字符和标识进行归类:ascii码中的内容用一个字节保存、亚洲的字符用3个字节保存,南亚的字符用三个字节保存…

那么以上哪类原因对质量影响最大啊?

(7)       Facebook

   注释。

    当行注释:# 被讲明内容

    多行注释:”’被讲授内容”’,或然”””被讲解内容”””

“它是大局解释器锁”

(8)       Redhat

  变量

    变量是何等?
 变量:把程序运维的中档结果一时半刻的留存内存里,以便后续的代码调用。

    变量定义的条条框框:

  • 变量名只好是 字母、数字或下划线的随便组合
  • 变量名的率先个字符不能够是数字
  • 以下入眼字无法宣称为变量名
    [‘and’, ‘as’, ‘assert’, ‘break’, ‘class’, ‘continue’, ‘def’, ‘del’,
    ‘elif’, ‘else’, ‘except’, ‘exec’, ‘finally’, ‘for’, ‘from’,
    ‘global’, ‘if’, ‘import’, ‘in’, ‘is’, ‘lambda’, ‘not’, ‘or’, ‘pass’,
    ‘print’, ‘raise’, ‘return’, ‘try’, ‘while’, ‘with’, ‘yield’] 

今世Computer的CPU日常是多核的,并且有点具有四个Computer。为了充裕利用多余的管理本事,操作系统定义了1种低端的协会叫做线程:三个经过(比方Chrome浏览器)能够生出八个线程并且指点内部系统。

(9)       豆瓣

  常量

    常量即指不改变的量,如pai 3.1415九二陆伍三..

只要1个进程是CPU密集型,那么其负载能够被多核同时管理,从而使得提升大诸多利用的进程。

那是您没用好而已,为何Python为那样慢。(10)   知乎

  流程序调控制之–if。

  if…else 语句

    单分支

   if 条件:
      满足条件后要执行的代码

    双分支

   """
   if 条件:
      满足条件执行代码
   else:
      if条件不满足就走这段
   """
   AgeOfOldboy = 48

   if AgeOfOldboy > 50 :
      print("Too old, time to retire..")
   else:
      print("还能折腾几年!")

Python的缩进有以下多少个规格:

  • 一流代码必须顶行写,即只要壹行代码本人不借助于于别的条件,那它必须无法进行别的缩进
  • 平等第其他代码,缩进必须1律

当小编写那篇小说时,小编的Chrome浏览器同时持有43个线程。注意,基于POSIX(举例MacOS和Linux)和Windows操作系统相比较,线程的组织和API是见仁见智的。操作系统也会管理线程的调治难题。

(1一)   春雨医师

  流程序调整制之–while循环。

    基本循环

 
while 条件:
     
    # 循环体
 
    # 如果条件为真,那么循环体则执行
    # 如果条件为假,那么循环体不执行

    循环中止语句 

要是在循环的进度中,因为一些原因,你不想一连循环了,怎么把它搁浅掉呢?那就用到break
或 continue 语句

  • break用于完全告竣2个巡回,跳出循环体试行循环前边的口舌
  • continue和break有点类似,不相同在于continue只是甘休这次巡回,接着还实践前边的巡回,break则完全甘休循环

  count = 0
  while count <= 100 : #只要count<=100就不断执行下面的代码
      print("loop ", count)
      if count == 5:
          break
      count +=1 #每执行一次,就把count+1,要不然就变成死循环啦,因为count一直是0

  print("-----out of while loop ------")

  while … else ..

    与别的语言else 一般只与if 搭配区别,在Python 中还有个while
…else 语句

    while 后边的else 成效是指,当while
循环正常奉行完,中间未有被break 中止的话,就会实践else前面包车型地铁言辞

    count = 0
    while count <= 5 :
        count += 1
      print("Loop",count)

    else:
        print("循环正常执行完啦")
    print("-----out of while loop ------")

    借使实践进程中被break啦,就不会执行else的语句啦

    count = 0
    while count <= 5 :
        count += 1
      if count == 3:break
        print("Loop",count)

    else:
        print("循环正常执行完啦")
    print("-----out of while loop ------")

 

 

 

借使您前边未曾做过10二线程编制程序,你供给快速熟习锁的概念。差距于单线程进度,你需求保险当内存中的变量被涂改时,10贰线程不会同时试图访问依旧转移同二个仓库储存地方。

(12)   等等

当CPython创立变量时,它会预先分配存储空间,然后总括当前变量的引用数目。那么些概念被喻为引用计数。假使引用计数为零,那么它将从系统中释放对应存款和储蓄区域。

三、            Python

那正是为啥在CPython中开创“一时”变量不会使利用占用大量的蕴藏空间——尤其是当使用中接纳了for循环这一类可能大量创制“一时”变量的构造时。

python动态语言,强类型语言

当存在八个线程调用变量时,CPython如何锁住引用计数成为了三个挑衅。而“全局解释锁”应运而生,它亦可谨慎调整线程的执行。无论有多少的线程,解释器每趟只好实行2个操作。

(一)    优点

那对Python的性质意味着如何呢?

(一)          
Python的原则性是“优雅”、“分明”、“简单”,所以Python程序看上去总是轻便易懂,初学者学Python,不但入门轻松,而且未来深切下去,能够编写制定那么些可怜万分复杂的顺序。

若是你的利用基于单线程、单解释器,那么斟酌速度那一点就毫无意义,因为去掉GIL并不会影响代码质量。

(2)          
开荒成效相当高,Python有相当有力的第一方库,基本上你想通过Computer完成别的功用,Python官方Curry都有照看的模块进行援助,直接下载调用后,在基础库的底蕴上再拓展支付,大大下跌开采周期,制止再次造轮子。

假定你想行使线程在单解释器(Python
进度)中落到实处产出,并且你的线程为IO密集型(比方网络IO或磁盘IO),你就会师到GIL争用的结果。

(三)          
高端语言——当您用Python语言编写程序的时候,你无需考虑诸如怎么着保管你的顺序选择的内部存款和储蓄器一类的最底层细节

假若您有五个互联网使用(举例Django)并且应用WSGI,那么每2个对此你的互连网选拔的央求将是一个单独的Python解释器,因而每一种请求唯有多少个锁。因为Python解释器运转一点也不快,一些WSGI便集成了力所能及使保证Python进程的“守护进度”  。

(四)          
可移植性——由于它的开源本质,Python已经被移植在广大阳台上(经过改变使它能够职业在不一致平台上)。假诺您小心地幸免采取依赖于系统的特征,那么您的兼具Python程序无需修改就大约可以在市场上保有的系统平台上运转

那正是说其余Python解释器的快慢又何以呢?

(五)          
可扩大性——假如您供给您的1段着重代码运转得更加快或许希望有些算法不领会,你能够把您的局部程序用C或C++编写,然后在您的Python程序中央银行使它们。

PyPy具备GIL,平时比CPython快至少三倍。

(六)          
可嵌入性——你能够把Python嵌入你的C/C++程序,从而向您的顺序用户提供脚本作用。

Jython未有GIL,因为在Jython中Python线程是用Java线程表示的,这得益于JVM内部存款和储蓄器管理种类。

(二)    缺点:

JavaScript是何等做到那或多或少的啊?

(1)           速度慢,Python
的周转速度比较C语言确实慢大多,跟JAVA比较也要慢一些,因此那也是不少所谓的大拿不屑于使用Python的首要性缘由,但实在那里所指的运作速度慢在大部情况下用户是无力回天直接感知到的,必须依据测试工具本事展示出来,比如您用C运贰个顺序花了0.0一s,用Python是0.一s,那样C语言直接比Python快了十倍,算是这一个夸张了,可是你是心有余而力不足间接通过肉眼感知的,因为一个常人所能感知的日子非常小单位是0.一伍-0.4s左右,哈哈。其实在大许多情况下Python已经完全能够知足你对程序速度的必要,除非您要写对进程须求极高的追寻引擎等,那种气象下,当然照旧提出您用C去得以达成的。

第二,所有的Javascript引擎使用标识加祛除的垃圾搜罗系统,而在此之前涉嫌GIL的骨干诉讼要求是CPython的存款和储蓄处清理计算法。

(贰)          
代码不可能加密,因为PYTHON是解释性语言,它的源码都是以名文情势存放的,可是本人不认为那到底一个欠缺,借使您的品种需求源代码必须是加密的,那您一齐头就不应有用Python来去得以达成。

JavaScript未有GIL,但因为它是单线程的,所以也并不供给GIL。

(3)          
线程无法动用多CPU难点,那是Python被人责怪最多的2个毛病,GIL即全局解释器锁(Global
Interpreter
Lock),是Computer程序设计语言解释器用于共同线程的工具,使得任什么日期刻仅有三个线程在实施,Python的线程是操作系统的原生线程。在Linux上为pthread,在Windows上为Win
thread,完全由操作系统调整线程的执行。3个python解释器进度内有一条主线程,以及多条用户程序的举办线程。纵然在多核CPU平台上,由于GIL的存在,所以禁止八线程的并行实践。关于这一个题目标妥胁化解办法,大家在以后线程和经过章节里再张开详尽探究。

JavaScript通过事件循环和承诺/回调形式来促成异步编制程序的产出。Python有与异步事件循环相似的进度。

(三)       Python解释器

 “因为它是解释型语言”

(1)           CPython

 

当我们从Python官网下载并安装好Python
2.七后,大家就间接获得了3个合法版本的解释器:CPython。这几个解释器是用C语言开荒的,所以叫CPython。在指令行下运转python正是运转CPython解释器。

自己不时听到那句话。小编认为那只是对于CPython实际运营格局的壹种简易表明。若是你在终点中输入python
myscript.py,那么CPython将对这段代码起初1雨后冬笋的读取,词法分析,解析,编译,解释和平运动行。

CPython是选择最广的Python解释器。教程的有着代码也都在CPython下试行。

本条历程中的首要步骤是在编写翻译阶段创立七个.pyc
文件,那一个字节码类别将被写入Python3下__pycache__/
路线中的二个文件(对于Python二,文件路线一样)。这一个手续不仅仅应用于脚本文件,也利用于具备导入的代码,包罗第壹方模块。

(2)           IPython

从而基本上时候(除非您写的代码只运转三回),Python是在讲授字节码并且本地实践。下边大家将Java和C#.NET相比较:

IPython是依据CPython之上的3个交互式解释器,也正是说,IPython只是在交互格局上装有进步,可是实行Python代码的效应和CPython是截然等同的。好比多数国产浏览器就算外观分化,但基本其实都以调用了IE。

Java编写翻译成壹门“中间语言”,然后Java虚拟机读取字节代码并即时编写翻译为机械代码。.NET的通用中间语言(CIL)是如出壹辙的,它的通用语言运营时刻(CL中华V)也采纳即时编写翻译的诀要转化为机械代码。

CPython用>>>作为提醒符,而IPython用In [序号]:作为提醒符。

那正是说,如果Python用的是和Java和C#平等的虚拟机和某种字节代码,为啥在标准测试中它却慢得多?首先,.NET和Java是选拔JIT编写翻译的。

(3)           PyPy

JIT,又称即时编写翻译,必要一种中间语言来把代码举行分块(大概叫数据帧)。预编写翻译(AOT,
Ahead of Time)器的陈设性保障了CPU能够在互动在此之前知道代码中的每壹行。

PyPy是另贰个Python解释器,它的目的是施行进度。PyPy选取JIT技能,对Python代码进行动态编写翻译(注意不是分解),所以可以鲜明增进Python代码的执行进程。

JIT本人不会使实行进程越来越快,因为它依然举行同一的字节码种类。然而,JIT允许在运维时开始展览优化。好的JIT优化器能够质量评定哪些部分进行次数比较多,那个片段被称作“热门”。然后,它将用更迅捷的代码替换它们,实现优化。

多方Python代码都足以在PyPy下运营,可是PyPy和CPython有局地是分化的,那就招致相同的Python代码在二种解释器下施行恐怕会有例外的结果。假若你的代码要放手PyPy下进行,就供给明白PyPy和CPython的分化点。

那就表示当计算机应用程序须要重新做一件业务的时候,它就会越来越地快。此外,大家要明了Java和C#是强类型语言(变量须要预约义),由此优化器能够对代码做越多的尽管。

(4)           Jython

PyPy使用即时编写翻译器,并且前文也有提到它比CPython更加快。那篇有关标准测试的著作介绍得越来越详细——什么版本的Python最快?

Jython是运维在Java平台上的Python解释器,能够一贯把Python代码编写翻译成Java字节码施行。

链接:

(5)           IronPython

IronPython和Jython类似,只可是IronPython是运作在微软.Net平台上的Python解释器,能够间接把Python代码编写翻译成.Net的字节码。

那么,为何CPython不使用即时编写翻译器呢?

Python的解释器繁多,但运用最常见的照旧CPython。若是要和Java或.Net平台相互,最佳的点子不是用Jython或IronPython,而是经过互连网调用来交互,确定保障各程序之间的独立性。

JIT存在一些缺点:个中3个是运营时间。CPython运营时间已经相对比较慢,PyPy比CPython还要慢2-三倍。无人不晓,Java虚拟机的启航行速度度异常的慢。为了消除这么些主题素材,.NET
CL卡宴在系统运转的时候就初步运转,但CLR的开垦职员还开采了特别运维CL中华V的操作系统来增长速度它。

ps:部分剧情摘自【金角高手等唐唐僧的日子】的小说

若果你有八个运维时刻十分长的Python进程,并且其代码能够被优化(因为它蕴涵前文所述的“热门”),那么JIT就可见起到异常的大作用。

不过,CPython适用于各类应用。因而,就算你选用Python开垦命令行应用程序,每一遍调用CLI时都无法不等待JIT运行,那将越发缓慢。

CPython必须尽量多地品尝不一样的案例以管教通用性,而把JIT插入到CPython中只怕会让那么些项目抱残守缺。

万一你想要借助JIT的本事,而且你的工作量还一点都十分的大,那么使用PyPy吧。

“因为它是1个动态类型语言”

 

在静态类型语言中,定义变量时必须证明类型。C, C++, Java, C#,
Go都以那种语言。

在动态类型语言中,类型的定义依然存在,可是这些变量的类型是动态变化的。

a = 1

a = “foo”

在地方这几个事例中,Python创立第贰个变量的时候用了平等的名字,可是变量类型是str(字符型),那样就对从前在内部存款和储蓄器中给a分配的半空中拓展了释放和再分配。

静态类型语言的那种规划并不是为了麻烦大家——它们是根据CPU的周转情势设计的。倘使最终要求将持有剧情都转载为轻易的二进制操作,那就必须将目的和类型转变为中低等数据结构。

Python自动达成了这一个进程,大家看不见,也没须求看见。

不必注解类型不是使Python变慢的缘故。Python语言的计划性使大家大约能够创设任何动态变量。大家得以在运作时替换对象中的方法,也能够胡乱地把初级系统调用赋给三个值。差不多怎么修改都足以。

幸而那种安顿使得优化Python变得卓殊费力。

为了表明本身的见识,笔者将动用3个MacOS中的应用。它是一个名称叫Dtrace的系统调用追踪工具。CPython发行版未有放开DTrace,由此你不能够不另行编写翻译CPython。以下演示中运用叁.陆.陆版本。

wget

unzip v3.6.6.zip

cd v3.6.6

./configure –with-dtrace

make

当今python.exe就要整条代码中接纳Dtrace追踪器。Paul罗斯尔就Dtrace做了一篇很棒的短演说。
你能够下载Python的DTrace运维文件来测试函数调用、实行时间、CPU时间、系统调用等各个逸事体。比方:

sudo dtrace -s toolkit/<tracer>.d -c ‘../cpython/python.exe
script.py’

DTrace运维文件:

发言链接:

py_callflow追踪器展现应用程序中的全部函数调用

因而,是Python的动态类型让它变慢的啊?

  • 比较和调换类型是耗费时间的,因为老是读取、写入变量或引用变量类型时都会进行检讨
  • 很难优化1种如此动态的言语。别的语言之所以那么快是因为他俩捐躯了自然的狡猾,从而加强了质量。
  • 刺探一下Cython,它结合了C-Static类型和Python来优化已知类型的代码,能够提供八四倍速度的质量升高。

结论

 

Python的悠悠重若是由于它动态和多用途的性状。它能够用于化解大约所不正常,然则越来越优化而飞快的代表方案恐怕存在。

但是,有壹部分措施能够通过运用异步计算,掌握分析工具,以及考虑选拔四个解释器来优化Python应用程序。

对于有个别运维时间相对不根本,并且即时编译器(JIT)可以提升功效的施用,可以牵挂采取PyPy。

对于品质优先并且有越多静态变量的代码部分,请思虑动用Cython。

二十八线程爬取表情包

有三个网址,叫做“斗图啦”,网站是:https://www.doutula.com/。这之中富含了恒河沙数的风趣的斗图图片,还蛮风趣的。有时候为了斗图要跑到那一个地点来找表情,实在有点困难。于是就发出了2个凶悍的主张,能够写个爬虫,把富有的表情都给爬下来。那几个网址对于爬虫来讲算是比较和煦了,他不会限制你的headers,不会限制你的拜会频率(当然,作为八个有素质的爬虫技术员,爬完赶紧撤,不要把人家庭服务务器搞垮了),不会限制你的IP地址,因而才具难度不算太高。可是有贰个主题素材,因为那里要爬的是图片,而不是文件消息,所以利用古板的爬虫是足以变成我们的须要,然则因为是下载图片所以速度异常慢,恐怕要爬1七个时辰都说禁止。由此那里我们打算接纳十二线程爬虫,一下能够把爬虫的频率进步好数倍。

1、分析网址和爬虫希图专门的学问:

创设具备页面U本田UR-VL列表:

此地大家要爬的页面不是“斗图啦”首页,而是最新表情页面https://www.doutula.com/photo/list/,那么些页面包括了具备的表情图片,只是是奉公守法时间来排序的而已。大家把页面滚动到最下边,能够看出这几个最新表情使用的是分页,当大家点击第三页的时候,页面包车型客车URL变成了https://www.doutula.com/photo/list/?page=2,而小编辈再回到第一页的时候,page又改成了1,所以那个翻页的URL实在相当粗略,后边那一串https://www.doutula.com/photo/list/?page=都以确定地点的,只是前边跟的数字不均等而已。并且我们能够观望,这些最新表情总共是有86九页,由此那里大家能够写个非凡简单的代码,来营造1个从一到86九的页面包车型地铁URL列表:

  1.  

    # 全局变量,用来保存页面的URL的

  2.  

    PAGE_URL_LIST = []

  3.  

    BASE_PAGE_URL = 'https://www.doutula.com/photo/list/?page='

  4.  

    for x in range(1, 870):

  5.  

    url = BASE_PAGE_URL + str(x)

  6.  

    PAGE_URL_LIST.append(url)

获得2个页面中持有的表情图片链接:

作者们早就获得了装有页面包车型客车链接,可是还尚未得到各样页面中表情的链接。经过分析,大家得以知晓,其实各类页面中表情的HTML要素构成没什么分歧的,因而大家只需求针对3个页面进行辨析,其余页面依据一样的规则,就能够得到全体页面包车型地铁神气链接了。这里大家以率先页为例,跟大家讲明。首先在页面中右键->检查->Elements,然后点击Elements最左侧的充裕小光标,再把鼠标放在随便三个神情上,这样上边的代码就牢固到那么些表情所在的代码地点了:

澳门葡京备用网址 1

01.png

可以见到,这一个img标签的class是等于img-responsive lazy image_dtz,然后大家再定位别的表情的img标签,开采持有的神采的img标签,他的class都是img-responsive lazy image_dtz

澳门葡京备用网址 2

02.png

澳门葡京备用网址 3

03.png

故此大家只要把多少从网络拉下来,然后再依据这一个规则举办领取就足以了。那里大家选取了三个第一方库,八个是requests,那些库是专门用来做互联网请求的。第二个库是bs4,那个库是专门用来把请求下来的数目开始展览辨析和过滤用的,假使未有设置好那八个库的,能够利用以下代码进行设置(我使用的是python二.7的版本):

  1.  

    #
    安装requests

  2.  

    pip install requests

  3.  

    #
    安装bs4

  4.  

    pip install bs4

  5.  

    #
    安装lxml解析引擎

  6.  

    pip install lxml

接下来大家以第三个页面为例,跟大家讲授怎样从页面中拿走具备表情的链接:

  1.  

    # 导入requests库

  2.  

    import requests

  3.  

    # 从bs4中导入BeautifulSoup

  4.  

    from bs4 import BeautifulSoup

  5.  

     

  6.  

    # 第一页的链接

  7.  

    url = 'https://www.doutula.com/photo/list/?page=1'

  8.  

    # 请求这个链接

  9.  

    response = requests.get(url)

  10.  

    # 使用返回的数据,构建一个BeautifulSoup对象

  11.  

    soup = BeautifulSoup(response.content,'lxml')

  12.  

    # 获取所有class='img-responsive lazy image_dtz'的img标签

  13.  

    img_list = soup.find_all('img', attrs={'class': 'img-responsive lazy image_dta'})

  14.  

    for img in img_list:

  15.  

    # 因为src属性刚开始获取的是loading的图片,因此使用data-original比较靠谱

  16.  

    print img['data-original']

诸如此类大家就可以在调控台看到本页中颇具的表情图片的链接就全体都打字与印刷出来了。

下载图片:

有图片链接后,还要对图纸展开下载管理,那里大家以一张图片为例:http://ws2.sinaimg.cn/bmiddle/9150e4e5ly1fhpi3ysfocj205i04aa9z.jpg,来看看Python中什么轻Panasonic载一张图片:

  1.  

    import urllib

  2.  

    url = 'http://ws2.sinaimg.cn/bmiddle/9150e4e5ly1fhpi3ysfocj205i04aa9z.jpg'

  3.  

    urllib.urlretrieve(url,filename='test.jpg')

如此就能够下载一张图纸了。

组合以上叁局地剧情:

如上3有个别,分别对,怎么着营造具有页面包车型地铁URL,一个页面中怎么着获取拥有表情的链接以及下载图片的秘技。接下来把那三部分构成在共同,就足以创设八个完全但效能不高的爬虫了:

  1.  

    # 导入requests库

  2.  

    import requests

  3.  

    # 从bs4中导入BeautifulSoup

  4.  

    from bs4 import BeautifulSoup

  5.  

    import urllib

  6.  

    import os

  7.  

     

  8.  

    # 全局变量,用来保存页面的URL的

  9.  

    PAGE_URL_LIST = []

  10.  

    BASE_PAGE_URL = 'https://www.doutula.com/photo/list/?page='

  11.  

    for x in range(1, 870):

  12.  

    url = BASE_PAGE_URL + str(x)

  13.  

    PAGE_URL_LIST.append(url)

  14.  

     

  15.  

     

  16.  

    for page_url in PAGE_URL_LIST:

  17.  

    # 请求这个链接

  18.  

    response = requests.get(page_url)

  19.  

    # 使用返回的数据,构建一个BeautifulSoup对象

  20.  

    soup = BeautifulSoup(response.content,'lxml')

  21.  

    # 获取所有class='img-responsive lazy image_dtz'的img标签

  22.  

    img_list = soup.find_all('img', attrs={'class': 'img-responsive lazy image_dta'})

  23.  

    for img in img_list:

  24.  

    # 因为src属性刚开始获取的是loading的图片,因此使用data-original比较靠谱

  25.  

    src = img['data-original']

  26.  

    # 有些图片是没有http的,那么要加一个http

  27.  

    if not src.startswith('http'):

  28.  

    src = 'http:'+ src

  29.  

    # 获取图片的名称

  30.  

    filename = src.split('/').pop()

  31.  

    # 拼接完整的路径

  32.  

    path = os.path.join('images',filename)

  33.  

    urllib.urlretrieve(src,path)

上述那份代码。能够完整的周转了。可是作用不高,毕竟是在下载图片,要3个个排队下载。若是能够利用拾2线程,在一张图片下载的时候,就完全能够去哀求别的图片,而不用持续等待了。因而作用比较高,以下将该例子改为十二线程来兑现。

贰、四线程下载图片:

此处四线程大家使用的是Python自带的threading模块。并且大家使用了一种名称为生产者和买主的格局,生产者专门用来从各类页面中收获表情的下载链接存款和储蓄到一个大局列表中。而顾客专门从那些全局列表中领到表情链接实行下载。并且供给小心的是,在二十八线程中采用全局变量要用锁来保险数据的壹致性。以下是102线程的爬虫代码(若是有看不懂的,能够看摄像,批注非常细致):

  1.  

    #encoding: utf-8

  2.  

     

  3.  

    import urllib

  4.  

    import threading

  5.  

    from bs4 import BeautifulSoup

  6.  

    import requests

  7.  

    import os

  8.  

    import time

  9.  

     

  10.  

    # 表情链接列表

  11.  

    FACE_URL_LIST = []

  12.  

    # 页面链接列表

  13.  

    PAGE_URL_LIST = []

  14.  

    # 构建869个页面的链接

  15.  

    BASE_PAGE_URL = 'https://www.doutula.com/photo/list/?page='

  16.  

    for x in range(1, 870):

  17.  

    url = BASE_PAGE_URL + str(x)

  18.  

    PAGE_URL_LIST.append(url)

  19.  

     

  20.  

    # 初始化锁

  21.  

    gLock = threading.Lock()

  22.  

     

  23.  

    # 生产者,负责从每个页面中提取表情的url

  24.  

    classProducer(threading.Thread):

  25.  

    defrun(self):

  26.  

    while len(PAGE_URL_LIST) > 0:

  27.  

    # 在访问PAGE_URL_LIST的时候,要使用锁机制

  28.  

    gLock.acquire()

  29.  

    page_url = PAGE_URL_LIST.pop()

  30.  

    # 使用完后要及时把锁给释放,方便其他线程使用

  31.  

    gLock.release()

  32.  

    response = requests.get(page_url)

  33.  

    soup = BeautifulSoup(response.content, 'lxml')

  34.  

    img_list = soup.find_all('img', attrs={'class': 'img-responsive lazy image_dta'})

  35.  

    gLock.acquire()

  36.  

    for img in img_list:

  37.  

    src = img['data-original']

  38.  

    if not src.startswith('http'):

  39.  

    src = 'http:'+ src

  40.  

    # 把提取到的表情url,添加到FACE_URL_LIST中

  41.  

    FACE_URL_LIST.append(src)

  42.  

    gLock.release()

  43.  

    time.sleep(0.5)

  44.  

     

  45.  

    # 消费者,负责从FACE_URL_LIST提取表情链接,然后下载

  46.  

    classConsumer(threading.Thread):

  47.  

    defrun(self):

  48.  

    print '%s is running' % threading.current_thread

  49.  

    while True:

  50.  

    # 上锁

  51.  

    gLock.acquire()

  52.  

    if len(FACE_URL_LIST) == 0:

  53.  

    # 不管什么情况,都要释放锁

  54.  

    gLock.release()

  55.  

    continue

  56.  

    else:

  57.  

    # 从FACE_URL_LIST中提取数据

  58.  

    face_url = FACE_URL_LIST.pop()

  59.  

    gLock.release()

  60.  

    filename = face_url.split('/')[-1]

  61.  

    path = os.path.join('images', filename)

  62.  

    urllib.urlretrieve(face_url, filename=path)

  63.  

     

  64.  

    if __name__ == '__main__':

  65.  

    # 2个生产者线程,去从页面中爬取表情链接

  66.  

    for x in range(2):

  67.  

    Producer().start()

  68.  

     

  69.  

    # 5个消费者线程,去从FACE_URL_LIST中提取下载链接,然后下载

  70.  

    for x in range(5):

  71.  

    Consumer().start()

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website