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.

参考答案:

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

因为GIL的原因,导致python的多线程并不是真正的多线程,一次只能执行一个线程。但是开启多线程也比单线程要好。因此如果运行的是计算密集型,也就是中间没有延时的,就使用进程。如果是io密集型,也就是读写的话,就可以考虑线程和协程。解决python的GIL问题有两个,一个换解释器,这个问题只有在CPython解释器中存在。第二个方法就是使用C语言编写子线程,然后导入进Python程序中。

深拷贝、浅拷贝

1. 浅拷贝

  • 浅拷贝是对于一个对象的顶层拷贝

通俗的理解是:拷贝了引用,并没有拷贝内容

2. 深拷贝

  • 深拷贝是对于一个对象所有层次的拷贝(递归)

进一步理解深拷贝

如果copy.copy拷贝的是元组,那么它不会进行浅拷贝,而仅仅是指向。

原因:元组是不可变类型,那么意味着数据一定不能进行修改,因此用copy.copy的时候它会进行自动判断,如果是元组它就是指向了它。

如果用copy.copy、copy.deepcopy对一个全部都是不可变类型的数据进行拷贝,那么他们结果相同,都是引用指向.。

如果拷贝的是一个拥有可变类型的数据,即使元组是最顶层,那么deepcopy依然是深拷贝,而copy.copy还是指向。

拷贝的其他方式

  • 分片表达式可以赋值一个序列

  • 字典的copy方法可以拷贝一个字典

注意点

浅拷贝对不可变类型和可变类型的copy不同

  1. copy.copy对于可变类型,会进行浅拷贝
  2. copy.copy对于不可变类型,不会拷贝,仅仅是指向

import导入模块

import aa 的过程是首先导入 aa这个模块,然后在当前程序中创建aa这个变量指向这个模块。

1. import 搜索路径

路径搜索

  • 从上面列出的目录里依次查找要导入的模块文件
  • '' 表示当前路径
  • 列表中的路径的先后顺序代表了python解释器在搜索模块时的先后顺序

程序执行时添加新的模块路径

sys.path.append('/home/itcast/xxx')
sys.path.insert(0, '/home/itcast/xxx') # 可以确保先搜索这个路径
In [37]: sys.path.insert(0,"/home/python/xxxx")
In [38]: sys.path
Out[38]:
['/home/python/xxxx',
'',
'/usr/bin',
'/usr/lib/python35.zip',
'/usr/lib/python3.5',
'/usr/lib/python3.5/plat-x86_64-linux-gnu',
'/usr/lib/python3.5/lib-dynload',
'/usr/local/lib/python3.5/dist-packages',
'/usr/lib/python3/dist-packages',
'/usr/lib/python3/dist-packages/IPython/extensions',
'/home/python/.ipython']

2. 重新导入模块

模块被导入后,import module不能重新导入模块,重新导入需用reload

3. 多模块开发时的注意点

# recv_msg.py模块
from common import RECV_DATA_LIST
# from common import HANDLE_FLAG
import common def recv_msg():
"""模拟接收到数据,然后添加到common模块中的列表中"""
print("--->recv_msg")
for i in range(5):
RECV_DATA_LIST.append(i) def test_recv_data():
"""测试接收到的数据"""
print("--->test_recv_data")
print(RECV_DATA_LIST) def recv_msg_next():
"""已经处理完成后,再接收另外的其他数据"""
print("--->recv_msg_next")
# if HANDLE_FLAG:
if common.HANDLE_FLAG:
print("------发现之前的数据已经处理完成,这里进行接收其他的数据(模拟过程...)----")
else:
print("------发现之前的数据未处理完,等待中....------")
# handle_msg.py模块
from common import RECV_DATA_LIST
# from common import HANDLE_FLAG
import common def handle_data():
"""模拟处理recv_msg模块接收的数据"""
print("--->handle_data")
for i in RECV_DATA_LIST:
print(i) # 既然处理完成了,那么将变量HANDLE_FLAG设置为True,意味着处理完成
# global HANDLE_FLAG
# HANDLE_FLAG = True
common.HANDLE_FLAG = True def test_handle_data():
"""测试处理是否完成,变量是否设置为True"""
print("--->test_handle_data")
# if HANDLE_FLAG:
if common.HANDLE_FLAG:
print("=====已经处理完成====")
else:
print("=====未处理完成====")
# main.py模块
from recv_msg import *
from handle_msg import * def main():
# 1. 接收数据
recv_msg()
# 2. 测试是否接收完毕
test_recv_data()
# 3. 判断如果处理完成,则接收其它数据
recv_msg_next()
# 4. 处理数据
handle_data()
# 5. 测试是否处理完毕
test_handle_data()
# 6. 判断如果处理完成,则接收其它数据
recv_msg_next() if __name__ == "__main__":
main()

以上面的图,如果其他两个模块使用“import  common”,那就是都指向同一个模块common;如果使用“from common import HANDLE_FLAG”,那么一开始就是HANDLE_FLAG直接指向common里面的HANDLE_FLAG而已,没有指向common,在后面的“HANDLE_FLAG = True”属于赋值语句,不会改变common里面的HANDLE_FLAG,而是重新创建一个值True,并指向它。(当然如果指向的值是列表list,那么采用".append"时,就可以修改common模块里面的值,但如果还是采用赋值语句就不行,相当于重新开辟一块内存空间了。)

为啥要封装

好处

  1. 在使用面向过程编程时,当需要对数据处理时,需要考虑用哪个模板中哪个函数来进行操作,但是当用面向对象编程时,因为已经将数据存储到了这个独立的空间中,这个独立的空间(即对象)中通过一个特殊的变量(__class__)能够获取到类(模板),而且这个类中的方法是有一定数量的,与此类无关的将不会出现在本类中,因此需要对数据处理时,可以很快速的定位到需要的方法是谁 这样更方便
  2. 全局变量是只能有1份的,多很多个函数需要多个备份时,往往需要利用其它的变量来进行储存;而通过封装 会将用来存储数据的这个变量 变为了对象中的一个“全局”变量,只要对象不一样那么这个变量就可以再有1份,所以这样更方便
  3. 代码划分更清晰

  

Python 高级的更多相关文章

  1. python 高级之面向对象初级

    python 高级之面向对象初级 本节内容 类的创建 类的构造方法 面向对象之封装 面向对象之继承 面向对象之多态 面向对象之成员 property 1.类的创建 面向对象:对函数进行分类和封装,让开 ...

  2. python高级之函数

    python高级之函数 本节内容 函数的介绍 函数的创建 函数参数及返回值 LEGB作用域 特殊函数 函数式编程 1.函数的介绍 为什么要有函数?因为在平时写代码时,如果没有函数的话,那么将会出现很多 ...

  3. python高级之装饰器

    python高级之装饰器 本节内容 高阶函数 嵌套函数及闭包 装饰器 装饰器带参数 装饰器的嵌套 functools.wraps模块 递归函数被装饰 1.高阶函数 高阶函数的定义: 满足下面两个条件之 ...

  4. python高级之生成器&迭代器

    python高级之生成器&迭代器 本机内容 概念梳理 容器 可迭代对象 迭代器 for循环内部实现 生成器 1.概念梳理 容器(container):多个元素组织在一起的数据结构 可迭代对象( ...

  5. python高级之面向对象高级

    python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两种,不像c++中的类有公有成员(pu ...

  6. python高级之网络编程

    python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及其源码分析 1.网络通信概念 说 ...

  7. python高级之多线程

    python高级之多线程 本节内容 线程与进程定义及区别 python全局解释器锁 线程的定义及使用 互斥锁 线程死锁和递归锁 条件变量同步(Condition) 同步条件(Event) 信号量 队列 ...

  8. python高级之多进程

    python高级之多进程 本节内容 多进程概念 Process类 进程间通讯 进程同步 进程池 1.多进程概念 multiprocessing is a package that supports s ...

  9. python高级之操作数据库

    python高级之操作数据库 本节内容 pymysql介绍及安装 使用pymysql执行sql 获取新建数据自增ID fetch数据类型设置 1.pymysql介绍及安装 在python2中连接数据库 ...

  10. matplotlib python高级绘图库 一周总结

    matplotlib python高级绘图库 一周总结 官网 http://matplotlib.org/ 是一个python科学作图库,可以快速的生成很多非常专业的图表. 只要你掌握要领,画图将变得 ...

随机推荐

  1. LeetCode 404. 左叶子之和(Sum of Left Leaves)

    404. 左叶子之和 404. Sum of Left Leaves LeetCode404. Sum of Left Leaves 题目描述 计算给定二叉树的所有左叶子之和. 示例: 3 / \ 9 ...

  2. php实现映射

    目录 映射 实现 链表实现: 二叉树实现 复杂度分析 映射 映射,或者射影,在数学及相关的领域经常等同于函数.基于此,部分映射就相当于部分函数,而完全映射相当于完全函数. 映射(Map)是用于存取键值 ...

  3. springboot(3):整合Servlet,filter,listener

    1.springboot整合Servlet(2种方式) 添加maven依赖:spring-boot-starter-web 1>通过注解扫描完成Servlet组件的注册(方式1) 步骤:需要3步 ...

  4. grpc proto文件生成java、.net实体类以及客户端代码

    背景 工作中对接对方服务是GRPC,对方只提供了proto契约文件,需要自己生成对应的实体类以及客户端代码,故记录下操作流程. Java 代码生成 实体类: 通过protoc插件生成实体类 在 htt ...

  5. SAS学习笔记47 Macro Quoting

    简单来说:Macro Quoting就是将具有特殊功能字符及字母组合的特殊功能隐藏掉.例如:让分号(;)不再表示一个语句的结束,而就是一个普普通通的字符:让GE不再表示大于等于的比较符,而就是两个普普 ...

  6. Spring Boot集成redis完整实例

    添加依赖: (Spring Data Redis) 启动redis: 配置文件中进行配置: redis基本使用思路: redis中不存在就查询数据库然后存入redis: 查看日志:

  7. 轻松玩转Ant Design Pro一

    ant design pro来源于ant design,其是一段自带样式的react组件,用于企业后台的漂亮的,可控的组件.ant design有很多组件和样式,不可能所有都记住,我们只要记住常用的, ...

  8. dfs的剪枝优化

    两个剪枝问题 1. 当两点的距离(需要走的步数)大于剩下的时间时 剪去 2.奇偶剪枝问题 如果起点到终点所需走的步数的奇偶性与时间奇偶性不同的时候 剪去 起点到终点步数的奇偶性的判断 首先 明确点的奇 ...

  9. [v]Windows下Git安装指南

    参考<Git权威指南>安装整理,图书配套网址参见[1] 1. Cygwin下安装配置Git 1. 在Windows下安装配置Git有2种不同的方案 (1)msysGit, (2)Cygwi ...

  10. LINUX CGROUP总结

    简介: Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU.内存.磁盘输入输出等).这个项目最早是由Go ...