更新了部分文档

pull/16/merge
jackfrued 2021-03-07 23:49:07 +08:00
parent 5f7b3586f3
commit 185055719c
9 changed files with 169 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@ -96,7 +96,7 @@ wb.save('考试成绩表.xlsx')
header_style = xlwt.XFStyle()
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
# 0 - 黑色、1 - 白色、2 - 红色、3 - 绿色、4 - 蓝色、5 - 黄色、6 - 粉色、7 - 青色
# 0 - 黑色、1 - 白色、2 - 红色、3 - 绿色、4 - 蓝色、5 - 黄色、6 - 粉色、7 - 青色
pattern.pattern_fore_colour = 5
header_style.pattern = pattern
titles = ('姓名', '语文', '数学', '英语')

View File

@ -1,10 +1,58 @@
## 第032课Python中的并发编程
现如今我们使用的计算机早已是多CPU或多核的计算机为此我们使用的操作系统基本都是支持“多任务”的操作系统这样的操作系统使得我们我们可以同时运行多个程序也可以将一个程序分解为若干个相对独立的子任务让多个子任务“齐头并进”的执行从而缩短程序的执行时间同时也让用户获得更好的体验。因此当下不管用什么编程语言进行开发实现让一个程序同时执行多个任务已经成为程序员的标配技能。为此我们需要先了解两个重要的概念多进程和多线程。
### 线程和进程
我们通过操作系统运行一个程序会创建出一个或多个进程进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动。简单的说进程是操作系统分配存储空间的基本单位每个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅助数据操作系统管理所有进程的执行为它们合理的分配资源。一个进程可以通过fork或spawn的方式创建新的进程来执行其他的任务不过新的进程也有自己独立的内存空间因此两个进程如果要共享数据必须通过进程间通信机制IPC来实现具体的方式包括管道、信号、套接字等。
一个进程还可以拥有多个并发的执行线索简单的说就是拥有多个可以获得CPU调度的执行单元这就是所谓的线程。由于线程在同一个进程下它们可以共享相同的上下文因此相对于进程而言线程间的信息共享和通信更加容易。当然在单核CPU系统中多个线程不可能同时执行因为在某个时刻只有一个线程能够获得CPU多个线程通过共享了CPU执行时间的方式来达到并发的效果。在程序中使用多线程技术通常都会带来不言而喻的好处最主要的体现在提升程序的性能和改善用户体验今天我们使用的软件几乎都用到了多线程技术这一点可以利用系统自带的进程监控工具如macOS中的“活动监视器”、Windows中的“任务管理器”来证实如下图所示。
![](res/macos-monitor.png)
这里,我们还需要跟大家说说另外两个概念:**并发**concurrency和**并行**parallel。并发是指同一时刻只能有一条指令执行但是多个线程对应的指令被快速轮换地执行。比如一个处理器它先执行线程 A 的指令一段时间,再执行线程 B 的指令一段时间,再切回到线程 A 执行一段时间。由于处理器执行指令的速度和切换的速度非常非常快人完全感知不到计算机在这个过程中有多个线程切换上下文执行的操作这就使得宏观上看起来多个线程在同时运行但微观上其实只有一个线程在执行。并行是指同一时刻有多条指令在多个处理器上同时执行并行必须要依赖于多个处理器。不论是从宏观上还是微观上多个线程都是在同一时刻一起执行的。在我们的课程中其实并不用严格区分并发和并行两个词所以我们把Python中的多线程、多进程以及异步I/O都视为实现并发编程的手段但实际上前面两者也可以实现并行编程。
### 多线程编程
Python标准库中`threading`模块的`Thread`类可以帮助我们非常轻松的实现多线程编程。我们用一个联网下载文件的例子来对比使用多线程和不使用多线程到底有什么区别,代码如下所示。
不使用多线程的下载。
```Python
```
> **说明**:上面的代码并没有真正实现联网下载的功能,而是通过`time.sleep()`休眠指定的时间模拟下载文件需要花费一段时间。
使用多线程的下载。
```Python
```
通过上面的代码可以看出,直接使用`Thread`类的构造器就可以创建线程对象,而线程对象的`start()`方法可以启动一个线程。线程启动后会执行`target`参数指定的函数当然前提是获得CPU的调度如果`target`指定的线程要执行的目标函数有参数,需要通过`args`参数为其进行指定。
除了上面的代码展示的创建线程的方式外,还可以通过继承`Thread`类并重写`run()`方法的方式来自定义线程,具体的代码如下所示。
```Python
```
通过上面的例子可以看出如果程序中有非常耗时的执行单元而这些耗时的执行单元之间又没有逻辑上的因果关系即B单元的执行不依赖于A单元的执行结果那么A和B两个单元就可以放到两个不同的线程中让他们并发的执行。这样做的好处除了减少程序执行的等待时间还可以带来更好的用户体验因为一个单元的阻塞不会造成程序的“假死”因为程序中还有其他的单元是可以运转的。
#### 守护线程
### 简单的总结
#### 资源竞争
#### 线程池
#### GIL问题

View File

@ -0,0 +1,90 @@
## 第033课Python中的并发编程
###创建进程
### 多进程和多线程的比较
由于GIL问题CPython中的多线程是不能很好发挥多核优势的如果想要发挥多核优势可以考虑使用多进程。对于多进程的程序每个进程都有属于自己的GIL所以多进程不会受GIL的影响能够很好的发挥多核CPU的优势。对于爬虫这类I/O密集型任务来说多线程和多进程影响差别并不大。对于计算密集型任务来说多进程相比多线程在效率上会有成倍的提升。
我们通过下面的代码来为大家证实多进程的优势。
```Python
"""
time python3 example22.py
real 0m11.512s
user 0m39.319s
sys 0m0.169s
使用多进程后实际执行时间为11.512秒而用户时间39.319秒约为实际执行时间的4倍
这就证明我们的程序通过多进程使用了CPU的多核特性而且这台计算机配置了4核的CPU
"""
import concurrent.futures
import math
PRIMES = [
1116281,
1297337,
104395303,
472882027,
533000389,
817504243,
982451653,
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419
] * 5
def is_prime(n):
"""判断素数"""
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def main():
"""主函数"""
with concurrent.futures.ProcessPoolExecutor() as executor:
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d is prime: %s' % (number, prime))
if __name__ == '__main__':
main()
```
### 进程间通信
### 简单的总结
对于Python开发者来说以下情况需要考虑使用多线程
1. 程序需要维护许多共享的状态尤其是可变状态Python中的列表、字典、集合都是线程安全的所以使用线程而不是进程维护共享状态的代价相对较小。
2. 程序会花费大量时间在I/O操作上没有太多并行计算的需求且不需占用太多的内存。
那么在遇到下列情况时,应该考虑使用多进程:
1. 程序执行计算密集型任务(如:字节码操作、数据处理、科学计算)。
2. 程序的输入可以并行的分成块,并且可以将运算结果合并。
3. 程序在内存使用方面没有任何限制且不强依赖于I/O操作读写文件、套接字等
> **温馨提示**:学习中如果遇到困难,可以加**QQ交流群**询问。
>
> 付费群:**789050736**,群一直保留,供大家学习交流讨论问题。
>
> 免费群:**151669801**,仅供入门新手提问,定期清理群成员。

View File

@ -1,4 +1,4 @@
## 第033Python中的并发编程
## 第034Python中的并发编程
### 异步编程

View File

@ -1,4 +1,4 @@
## 第034课用Python访问MySQL数据库
## 第035课用Python程序操作MySQL
如果要在程序中实现数据持久化一个特别常见的方案就是接入关系型数据库。我们之前提到过持久化这个概念简单的说就是将内存中的数据转移到硬盘上以便长久的保存数据。接下来我们以MySQL数据库为例来讲解在Python程序中如何使用MySQL实现数据持久化我们这里不会介绍MySQL和关系型数据库的知识如果没有对应的背景知识大家可以跳过这一课或者移步到我的Python-100-Days项目中[《关系型数据库MySQL》](https://github.com/jackfrued/Python-100-Days/blob/master/Day36-40/36-38.%E5%85%B3%E7%B3%BB%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%BA%93MySQL.md)一文来了解关于关系型数据库和MySQL的知识。如果想了解在Windows或macOS环境下如何安装MySQL数据库可以点击[传送门1](https://cloud.tencent.com/developer/article/1636375)或[传送门2](https://juejin.im/post/6844903831298375693)查看对应的文章。

View File

@ -1,4 +1,4 @@
## 第035课用Python绘制统计图表
## 第036课用Python程序操作Redis

View File

@ -0,0 +1,13 @@
## 第037课用Python程序操作MongoDB
### 简单的总结
> **温馨提示**:学习中如果遇到困难,可以加**QQ交流群**询问。
>
> 付费群:**789050736**,群一直保留,供大家学习交流讨论问题。
>
> 免费群:**151669801**,仅供入门新手提问,定期清理群成员。

View File

@ -0,0 +1,13 @@
## 第038课用Python程序绘制统计图表
### 简单的总结
> **温馨提示**:学习中如果遇到困难,可以加**QQ交流群**询问。
>
> 付费群:**789050736**,群一直保留,供大家学习交流讨论问题。
>
> 免费群:**151669801**,仅供入门新手提问,定期清理群成员。