Python 整数缓存机制
首先在终端中输入python
,打开解释器,输入以下测试代码:
首先在终端中输入python
,打开解释器,输入以下测试代码:
CPython 中的 GIL:影响与应对方法
global interpreter lock:
The mechanism used by the CPython interpreter to assure that only one thread executes Python bytecode at a time. This simplifies the CPython implementation by making the object model (including critical built-in types such as dict) implicitly safe against concurrent access. Locking the entire interpreter makes it easier for the interpreter to be multi-threaded, at the expense of much of the parallelism afforded by multi-processor machines.
However, some extension modules, either standard or third-party, are designed so as to release the GIL when doing computationally intensive tasks such as compression or hashing. Also, the GIL is always released when doing I/O.
Past efforts to create a “free-threaded” interpreter (one which locks shared data at a much finer granularity) have not been successful because performance suffered in the common single-processor case. It is believed that overcoming this performance issue would make the implementation much more complicated and therefore costlier to maintain.
全局解释程序锁:
全局解释程序锁(GIL)是 CPython 解释器的一个特性,确保一次只有一个线程可以执行 Python 字节码。GIL 的存在简化了 CPython 的实现,通过隐式地为对象模型提供并发访问安全性,甚至包括关键的内置类型,如字典。虽然全局解释程序锁会限制多线程环境中并行执行的能力,但通过将同步复杂性集中到解释器级别,它使得解释器更容易支持多线程。然而,这也导致多核处理器提供的并行性大部分被消耗。
不过,一些扩展模块(无论是标准的还是第三方的)被设计为在执行计算密集型任务(如压缩或散列)时会释放 GIL。此外,在执行 I/O 操作时,GIL 总是会被释放。
过去创建“自由线程”解释器(以更细的粒度锁定共享数据的解释器)的努力没有成功,因为在常见的单处理器情况下性能受到影响。据信,克服该性能问题将使实现复杂得多,并且因此维护成本更高。
不同 Python 解释器的特点及 GIL 影响
Python 生态系统中有多种 Python 解释器实现,每个实现都有其独特的特点:
CPython 作为使用 C 语言开发的标准解释器,存在全局解释器锁(GIL)的问题,从而导致多线程无法充分利用多核 CPU。
Jython 和 IronPython:由于基于 Java 和 .NET 运行时,不存在 GIL 问题,可以在多核 CPU 上充分发挥优势。
PyPy:虽然 PyPy 也有 GIL,但其使用 JIT 编译技术,部分优化了 GIL 带来的问题。
Cython:Cython 本身并非独立的解释器,但它可以通过编译成 C 语言的扩展来提高 Python 解释器的效率,不受 GIL 影响。
为什么 CPython 中存在 GIL?
CPython 中存在全局解释器锁(GIL)的主要原因是其历史和设计初衷。
历史背景: Python 最初在单核 CPU 时代诞生,其设计初衷并未考虑多线程并发执行的场景。在此背景下,设计师并没有着重解决多线程竞争问题。
引用计数内存管理机制: CPython 主要使用引用计数内存管理机制。然而,这种机制并不是线程安全的。具体而言,引用计数机制在多线程环境中容易出现问题,多个线程同时对对象引用计数进行增减操作可能引发竞争条件和线程安全问题。
为了避免这些问题,CPython 在执行 Python 字节码时引入了 GIL。这个机制确保同一时刻只有一个线程可以执行 Python 字节码,从而简化了内存管理。然而,这也限制了在多核 CPU 下实现真正的并发执行。
尽管 GIL 在某些情况下降低了多线程编程的便利性,但它在某些方面也有好处,例如在 I/O 密集型任务中释放 GIL,允许其他线程执行。
CPython 使用 C 扩展库: CPython 广泛使用 C 语言扩展库来提升性能。在多线程环境下,C 扩展库需要自己实现线程同步,这可能增加复杂性和错误的可能性。
降低 GIL 影响的方法:
降低 GIL 影响的策略包括但不限于以下方法:
Python 中的迭代器和生成器是用于处理可迭代对象的强大工具。它们有一些共同点,但也有一些重要的区别。
迭代器(Iterators):
__iter__()
和 __next__()
方法。iter()
方法可以将列表、元组、集合、字符串等可迭代对象转换为迭代器。next()
方法逐个访问元素。next()
方法会引发 StopIteration
异常。1 | # 创建一个可迭代对象(列表) |
在这个示例中,将列表my_list
转换为迭代器my_iterator
,然后使用next()
方法逐个访问迭代器的元素。当没有更多的元素可迭代时,next()
方法会引发StopIteration
异常,我们通过异常处理来结束循环。
生成器(Generators):
yield
关键字替代 return
返回值,将函数变成生成器对象。生成器是生成元素的,迭代器是访问集合元素的一种方式。
1 | # 创建一个生成器函数 |
迭代器用于按需访问集合元素,而生成器用于按需生成元素
首先是python的基本数据类型:
Number(数字) String(字符串) bool(布尔类型) List(列表) Tuple(元组) Set(集合) Dictory(字典)
单个前导下划线:
用于表示该变量是模块内部使用的,作为约定,告诉其他开发者这不是公共接口的一部分,不建议直接访问
1 | class MyClass: |
单个末尾下划线
避免与Python关键字或者内置函数名命名冲突时,可以使用单个末尾下划线来重命名变量,如class_
可以避免与class
冲突
class_ = 'test'
print(class_) # 输出: test
------------------------------
class= 'test'
File "<stdin>", line 1
class= 'test'
^
SyntaxError: invalid syntax
双前导下划线
名称修饰,保护父类属性的访问,防止子类属性覆盖父类属性,访问方法obj._类名__属性名
1 | class Parent: |
双前导和双末尾下划线
用于标识特殊方法(魔术方法),如 __init__
(构造方法)、__str__
(字符串表示方法)。
预定义的特殊名称,如,__name__
是一个包含当前模块名称的特殊变量。__file__
包含当前模块的文件路径。
1 | class MyClass: |
单个下划线:
用来表示无关紧要的变量
1 | for _ in range(5): |
在交互式解释器中,_
指向最后一次执行的表达式
结果
1 | 4+8 |
报错信息:
1 | urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='ssr4.scrape.center', port=443): Max retries exceeded with url: /page/1 (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)'))) |
SSL介绍:
SSL(Secure Sockets Layer)验证是在建立HTTPS连接时进行的一种验证过程。SSL验证的目的是确保服务器的身份,并验证通信双方之间的信任关系。以下是SSL验证的基本过程:
客户端请求建立SSL连接:当客户端(通常是Web浏览器)向服务器发送HTTPS连接请求时,它将尝试与服务器建立SSL连接。
服务器发送数字证书:如果服务器支持SSL,它会将包含数字证书的响应发送给客户端。数字证书由经过可信认证的第三方机构(证书颁发机构)签发,并包含了服务器的公钥、服务器的身份信息以及其他相关信息。
客户端验证数字证书:客户端接收到服务器发送的数字证书后,会对证书进行验证。验证过程包括以下几个方面:
a. 校验证书的签发机构:客户端会检查证书是否由被客户端信任的可信证书颁发机构签发。
b. 检查证书的有效期:客户端会验证证书是否在有效期内,即确认证书尚未过期。
c. 验证服务器域名:客户端会核对证书中的服务器域名与客户端请求的域名是否匹配。这可以防止中间人攻击等安全威胁。
d. 检查证书的撤销状态:客户端会查询证书撤销列表(CRL)或在线证书状态协议(OCSP)服务器,确认证书是否被吊销。
客户端生成会话密钥:一旦客户端验证通过,它会生成一个临时的会话密钥(也称为”对称密钥”或”会话密钥”),用于该SSL会话的后续加密和解密操作。
安全数据传输:客户端使用服务器的公钥对会话密钥进行加密,并将加密后的会话密钥发送给服务器。服务器使用自己的私钥解密接收到的会话密钥。之后,客户端和服务器之间的通信将使用该会话密钥进行对称加密和解密。
通过SSL验证过程,客户端可以验证服务器的身份,并确保与服务器之间建立了安全的通信通道。这种验证过程可以帮助防止中间人攻击、欺骗和数据篡改等安全威胁。同时,SSL验证还为用户提供了信任和可靠性,因为证书是由可信的第三方机构签发的,代表了服务器的身份和认证信息。
使用requests.get(verify=False)
关闭ssl验证。urllib3.disable_warnings()
禁用 urllib3 库中的 SSL 证书验证警告
Python常用的魔术方法有
__init__
,对象被创建后调用,用于初始化对象的属性。
__new__
,对象被创建之前被调用,
__str__
,用于打印该对象展示给用户的字符串信息。
__repr__
,用于开发调试时,给开发人员看的打印对象的详细信息
__len__
,用于获取容器对象的元素个数。
__call__
,允许对象像函数一样被调用,可以传递参数。
__iter__
,返回一个迭代器,允许对象成为一个可以迭代的容器,常和__next__
一起使用,