HiKariのTechLab

光の技术屋


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 站点地图

  • 搜索

【Hard Python】【第三章-GC】1、引用计数与内存释放机制

发表于 2022-03-12 | 更新于 2024-04-07 | 分类于 Hard Python

对于编程语言runtime来说,建立起良好运转GC机制是非常必要的,像Java和Go,其GC机制都经历了复杂的演化,当然同时也为编程语言带来了更好的性能,这也是为什么这两门语言能成为主流服务端语言的原因之一。

相对于Java和Go,python的GC机制是相对简约的,其中最基础的机制之一就是引用计数。当对象生成时引用计数为1;对象被其它对象引用时引用计数增加1;对象没有被引用,又退出作用域的话,引用计数归0;引用计数归0后,对象被销毁。

我们可以通过一个例子对引用计数机制进行研究:

1
2
3
def test_ref():
a = '123456789123456789'
del a

其反编译的结果是:

阅读全文 »

【Hard Python】【第二章-异步IO】3、async/await的源码实现

发表于 2022-02-26 | 更新于 2024-04-07 | 分类于 Hard Python

说完了asyncio事件循环是如何运行异步任务的,接下来back to basic,我们一起看看async和await两个原语具体代表了什么含义。

首先是async,async通常用来修饰一个函数,表示这个函数会返回一个协程。比如说:

1
2
3
4
5
6
7
async def _coro_maker(i):
print(i + 1)


def test_async():
c = _coro_maker(1)
asyncio.run(c)

对_coro_maker进行反编译,得到这样的结果:

阅读全文 »

【Hard Python】【第二章-异步IO】2、异步任务在事件循环中的执行

发表于 2022-02-20 | 更新于 2024-04-07 | 分类于 Hard Python

接续第一话的内容,事件循环在创建之后,又是如何运行协程任务以及异步IO任务的?
​
由asyncio.run的代码可知,loop.run_until_complete是运行协程的方法。其定义如下:

阅读全文 »

【Hard Python】【第二章-异步IO】1、asyncio事件循环的创建

发表于 2022-02-12 | 更新于 2024-04-07 | 分类于 Hard Python

python3中增加的重要特性之一即为asyncio,其提供了异步编程的原语支持,从而能够让python在事件驱动、协程协同等方面的编程场景大杀四方。

事件循环EventLoop是异步编程中的核心概念之一。python的异步IO,就从事件循环的实现开始讲起。

首先看一段示例代码:

1
2
3
4
5
6
7
8
9
async def _test_run_main():
for i in range(3):
await asyncio.sleep(1)
print(f'[test_run] {i}')


def test_run():
coro = _test_run_main()
asyncio.run(coro)

通过async def定义的函数,其返回值是一个异步协程coroutine。协程相当于是事件循环里的一个单位任务,通过asyncio.run接口就可以将其运行起来。因此我们先来看asyncio.run的实现:

阅读全文 »

【Hard Python】【第一章-多进程】3、Pool,多任务并行进程池

发表于 2022-01-30 | 更新于 2024-04-07 | 分类于 Hard Python

前面讲了进程创建与进程通信的内容,接下来讲一下多进程编程最能发挥的地方。对于同时运行多个同质任务来讲,采用multiprocessing.Pool进程池去管理是最方便的。Pool的用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from multiprocessing import Pool, process
import os
import pprint


def _test_func(a, b):
result = a + b
print(f'{os.getpid()}: {result}')
return result


def test_pool():
test_data = [(2 * i, 2 * i + 1) for i in range(16)]
with Pool(4) as p:
pprint.pprint(process.active_children())
results = p.starmap(_test_func, test_data) # starmap指iterable的unpack,*args这样,详情看源码注释
print(f'{os.getpid()}: {results}') # 得到_test_func的所有结果


if __name__ == '__main__':
test_pool()

打印出来的结果,可能是这样子的:

阅读全文 »

【Hard Python】【第一章-多进程】2、Pipe和Queue,进程间通信

发表于 2022-01-22 | 更新于 2024-11-03 | 分类于 Hard Python

第一话详细讲解了Process新进程是如何被创建的,接下来就来讲一下进程之间有什么通信的方法。

要在multiprocessing中实现进程间通信,最直接的方法是采用Pipe或者Queue。其用法如下:

阅读全文 »

【Hard Python】【第一章-多进程】1、Process,新进程的诞生

发表于 2022-01-16 | 更新于 2024-04-07 | 分类于 Hard Python

在python中,如果要做多任务并行的编程,必须要掌握multiprocessing库的相关运用。在python的multiprocessing官方文档中,已然详细给出了multiprocessing库的相关用法。多进程编程其实还是有很多坑存在的,为了进一步探索python多进程的机制,提升对python多进程编程的理解,本篇文章会对多进程模块的实现进行一次详细的剖析。

多进程编程的第一话,首先来聊聊一个新的python子进程是如何诞生的。

首先我们需要了解这么一个事情,python创建的进程之间模块状态是相互隔离的。在多进程的场景下,代码中定义的各种变量,其值并不一定会共享。我们举个例子:

阅读全文 »

【Hard Python】前言

发表于 2022-01-08 | 更新于 2024-04-07 | 分类于 Hard Python

写完Medium Python之后,不知不觉就有开始继续写Hard Python的冲动。择日不如撞日,心动不如行动,2022年开篇,果断将Hard Python提上日程。

截至2021年底,python依旧是最热门的语言之一,随着3.10、3.11及后续版本的发布,python的runtime在功能及性能上都会有较大的提升。时至今日,提到技术应用最广泛的语言,除了python,还会有另外的吗?排除区块链、游戏、音视频里较为深度的领域,基本上各种技术业务场景,都会有python的影子。

可以说,python是编程界的一把瑞士军刀。如果我们能更加深入的了解python各个重点模块的技术原理,不仅对于我们理解这门语言以及编程语言相关技术有益处,并且以后我们在面对一些python的编程场景时也会更加得心应手。

在先前已经写过两个python系列,分别是Easy Python以及Medium Python。在Easy Python中,对python的各种基础概念以及实用场景介绍了相关案例;而在Medium Python中,通过源码分析的方式,剖析了python内部某些语言特性的实现,讲述了许多python相关的冷知识。这次Hard Python,还是回归本源,将会挑选一些python内部比较重点的基础模块进行深入剖析讲解,争取让每一位阅读本系列文章的同学对python这门语言有更加全新的理解。

话不多说,准备上菜!

目录

  • 第一章:多线程
    • 1、Process,新进程的诞生
    • 2、Pipe和Queue,进程间通信
    • 3、Pool,多任务并行进程池
  • 第二章:异步IO
    • 1、asyncio事件循环的创建
    • 2、异步任务在事件循环中的执行
    • 3、async/await的源码实现
  • 第三章:GC
    • 1、引用计数与内存释放机制
    • 2、python的GC流程
  • 第四章:日志
    • 1、Logger与Manager的源码实现
    • 2、日志消费者Handler的实现
  • 第五章:字符串
    • 1、unicode,py3的字符串实现
    • 2、re,正则表达式源码详解

【Python随笔】如何提取python函数的接口定义信息

发表于 2021-12-12 | 更新于 2024-04-07 | 分类于 Python随笔

在某些python框架底层的开发需求中,需要通过一些类似反射的手段,提取函数接口的信息,从而对一系列函数接口进行管理。本篇文章就来粗浅谈一下,如何提取python函数的接口定义信息。

function对象的信息

首先我们拿一个函数来试试手:

1
2
3
4
5
def myprinter(s: str, /, e: str = '\n', *, prefix: Any = '') -> Tuple[bool, str]:
"""hello world"""
msg = str(prefix) + s + e
print(msg, end='')
return True, msg

这个函数myprinter采用了新的语法糖/以及*,/的左边表示强制位置参数(positional-only arguments),*的右边表示强制关键字参数(keyword-only arguments),而两者中间的参数在使用时以位置参数或者是关键字参数的形式表达都可以。

要提取这个函数的信息,我们首先要知道函数本身也是一种对象。因此,可以用到dir函数,遍历这个对象的属性,从而提取所有属性的值。

通过dir导出函数对象的属性与值,打印的结果如下:

阅读全文 »

【游戏开发】踩坑UE4的Python脚本插件

发表于 2021-11-21 | 更新于 2024-04-07 | 分类于 游戏开发

UE4以C++为基础,在游戏开发需求当中,官方推崇的是Blueprint可视化编程,而除此之外像UnLua、puerts等解决方案也提供了lua、ts等其它脚本语言的支持。至于python,UE4本身就有插件支持,叫做PythonScriptPlugin,启用插件后,在编辑器里,可以输入python代码执行一系列命令。在最新的4.27版本中,python的版本是3.7.7。

回到正题,之所以这篇文章标题叫踩坑,是因为真的踩坑了——尝试用PythonScriptPlugin来编写UE4的游戏逻辑,最终放弃。PythonScriptPlugin适合做一些驱动编辑器的操作,或者是做一些静态资源检查相关的工作(其实这个插件真名就叫Python Editor Script Plugin),如果用它来写游戏逻辑的话,很多必须的内容都难以支持。但不管怎么说,既然踩坑了还是要分享点东西出来,因此这篇文章先粗浅谈一下PythonScriptPlugin的工作流。

阅读全文 »
1…91011…20
ひかり.HDQ

ひかり.HDQ

talk is cheap, code is rich
191 日志
14 分类
415 标签
GitHub Mail CSDN Juejin Steam Bilibili
© 2019 – 2025 ひかり.HDQ
|