个人博客

记录工作中的点点滴滴


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

  • 搜索

python_面向对象

发表于 2019-12-31 | 更新于: 2019-12-31 | 分类于 Python
| 字数统计: 10.1k 字 | 阅读时长 ≈ 37 分钟

面向对象(OOP)基本概念

面向对象编程 —— Object Oriented Programming 简写 OOP

01. 面向对象基本概念

  • 我们之前学习的编程方式就是 面向过程 的
  • 面相过程 和 面相对象,是两种不同的 编程方式
  • 对比 面向过程 的特点,可以更好地了解什么是 面向对象

1.1 过程和函数(科普)

  • 过程 是早期的一个编程概念
  • 过程 类似于函数,只能执行,但是没有返回值
  • 函数 不仅能执行,还可以返回结果
阅读全文 »

python_闭包和装饰器

发表于 2019-12-31 | 更新于: 2019-12-31 | 分类于 Python
| 字数统计: 3.3k 字 | 阅读时长 ≈ 13 分钟

闭包

1. 函数引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def test1():
print("--- in test1 func----")

# 调用函数
test1()

# 引用函数
ret = test1

print(id(ret))
print(id(test1))

#通过引用调用函数
ret()

运行结果:

1
2
3
4
--- in test1 func----
140212571149040
140212571149040
--- in test1 func----
阅读全文 »

python_正则表达式

发表于 2019-12-31 | 更新于: 2019-12-31 | 分类于 Python
| 字数统计: 3.6k 字 | 阅读时长 ≈ 16 分钟

正则表达式

re模块操作

在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为re

1. re模块的使用过程

1
2
3
4
5
6
7
8
9
10
#coding=utf-8

# 导入re模块
import re

# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)

# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
阅读全文 »

python_模块和包

发表于 2019-12-31 | 更新于: 2019-12-31 | 分类于 Python
| 字数统计: 1.6k 字 | 阅读时长 ≈ 6 分钟

模块和包

01. 模块

1.1 模块的概念

模块是 Python 程序架构的一个核心概念

  • 每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
  • 模块名 同样也是一个 标识符,需要符合标识符的命名规则
  • 在模块中定义的 全局变量 、函数、类 都是提供给外界直接使用的 工具
  • 模块 就好比是 工具包,要想使用这个工具包中的工具,就需要先 导入 这个模块

1.2 模块的两种导入方式

1)import 导入

1
import 模块名1, 模块名2

提示:在导入模块时,每个导入应该独占一行

1
2
import 模块名1
import 模块名2

阅读全文 »

python_扩展知识点

发表于 2019-12-31 | 更新于: 2019-12-31 | 分类于 Python
| 字数统计: 13.8k 字 | 阅读时长 ≈ 59 分钟

GIL(全局解释器锁)

GIL面试题如下

描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因。

Guido的声明:http://www.artima.com/forums/flat.jsp?forum=106&thread=214235
he language doesn’t require the GIL – it’s only the CPython virtual machine that has historically been unable to shed it.

单线程死循环

单独执行该文件会占满一个CPU核心数(相当于单进程单线程),两个窗口执行该文件会占满两个CPU核心数(相当于两进程两线程)

1
2
3
4
5
6
#!/usr/bin/env python
#-*- coding: utf-8 -*-

# 主线程死循环,占满CPU
while True:
pass # 占位符,空语句,还是要执行的

两个线程死循环

单独执行该文件每个CPU核心会占一半(单进程两线程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
#-*- coding: utf-8 -*-

from threading import Thread

# 子线程死循环
def a():
while True:
pass

t = Thread(target=a)
t.start()

# 主线程死循环
while True:
pass

两个进程死循环

单独执行该文件会占满二个CPU核心数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
#-*- coding: utf-8 -*-

from multiprocessing import Process

# 子进程死循环
def a():
while True:
pass

if __name__ == '__main__':
t = Process(target=a)
t.start()
# 主进程死循环
while True:
pass

总结:多线程并不是真正的并行,而是伪并行,也就是并发。原因就是因为线程有GIL全局解释器锁。只有进程才是真正的并行

参考答案

  1. Python语言和GIL没有半毛钱关系。仅仅是由于历史原因在Cpython虚拟机(C语言解释器)中难以移除GIL。(其他python解释器没有GIL,比如java语言写的jpython解释器)
  2. GIL:全局解释器锁。每个线程在执行的过程都需要先获取GIL,保证同一时刻只有一个线程可以执行代码。
  3. 线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL Python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)或Python 2.x,tickets计数达到100

    计算密集型:程序没有延时,一直在计算数据;IO密集型:输入输出,读写操作
    线程和协程适用于IO密集型,计算密集型考虑使用进程。

  4. Python使用多进程是可以利用多核的CPU资源的。
  5. 多线程爬取比单线程性能有提升,因为遇到IO阻塞会自动释放GIL锁

使用c语言来解决GIL问题

子线程使用的是c语言的函数,此时单独执行该文件,会占满两个CPU核心

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from ctypes import *
from threading import Thread

# 加载动态库
# 把一个C语言编译成一个动态库文件的命令(linux平台)
# gcc libdead_loop.c -shared -o libdead_loop.so
lib = cdll.LoadLibrary("./libdead_loop.so")

# 创建一个子线程,让其执行c语言编写的函数(DeadLoop),此函数是一个死循环
t = Thread(target=lib.DeadLoop)
t.start()

# 主线程
while True:
pass

如何解决GIL

  1. 换python解释器,不使用Cpython解释器,使用jpython解释器等
  2. 用其他语言来替代线程中的代码,不如上例中的c语言,(胶水语言)
阅读全文 »
1…212223…29
永夜初晗凝碧天

永夜初晗凝碧天

Linux,Python,MySQL,ELK Stack,K8S,Docker

141 日志
55 分类
60 标签
RSS
QQ E-Mail
友情链接
  • 博客园
  • 百度
近期文章
  • Elasticsearch IK 分词器
  • 为Elasticsearch启动https访问
  • FastAPI框架入门 基本使用, 模版渲染, form表单数据交互, 上传文件, 静态文件配置
  • Elasticsearch:使用_update_by_query更新文档
  • Solutions:安全的APM服务器访问
© 2019 — 2020 永夜初晗凝碧天
博客全站字数统计 : 412.1k 字 ||载入天数...载入时分秒...
本文总阅读量次 || 本站访客数人次 || 本站总访问量次