HiKariのTechLab

光の技术屋


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 站点地图

  • 搜索

【Python随笔】python多线程什么情况下可以并行?什么情况下不能?

发表于 2022-07-03 | 更新于 2024-04-07 | 分类于 Python随笔

在python面试里,多线程是避不开的话题,其中一个经典问题就是,多线程threading.Thread是不是并行运行。这个问题的答案,说是也不对,说不是也不对,得分情况讨论。本文就带领大家,分析并回答这个问题。

我们用一段代码来做实验:

阅读全文 »

【Python随笔】掌握子进程subprocess模块的使用方法

发表于 2022-07-02 | 更新于 2024-04-07 | 分类于 Python随笔

在python开发期间,很多时候我们会需要执行一段cmd终端命令,或者是执行其他程序返回stdout或者文件输出结果。这种时候,我们就需要用到subprocess模块。虽然我们用os.system也可以达到执行命令的需求,但用os.system只是干发一段命令,对于执行命令的程序,我们没有办法跟踪它的内部状态以及执行结果,因此从稳定性的角度来讲不是一个好的选择。因此,本篇文章讲解下subprocess子进程模块的的基础应用,让没用过这个模块或是经常踩坑的同学都避避坑。

subprocess模块的官方文档在这里,最核心的单位是subprocess.Popen类,它描述了一个正在运行中的进程。subprocess最基础的用法是subprocess.run,我们入参一段cmd终端命令,run方法内部就会启动一个Popen对象执行这个命令,等待命令执行结束后,返回这个命令执行的退出码retcode,标准输出流内容stdout以及标准错误流内容stderr。我们可以从源码中详细捋一下subprocess.run的流程:

阅读全文 »

【极客日常】vue3中实现Array数组更新的方法

发表于 2022-06-17 | 更新于 2024-07-20 | 分类于 极客日常

近期由于工作原因,开始了解vue3的内容。vue3相对于vue2采用了组合式的描述,原来的写法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default {
name: 'HelloWorld',
data() {
return {
a: 1,
b: 2,
}
},
mounted() {
this.a = 3
},
methods: {
onConfirm() {
console.log(this.a)
}
}
}

而到了vue3,提倡的写法变成了:

阅读全文 »

【极客日常】通过motrix启动逻辑初探electron的项目结构

发表于 2022-06-05 | 更新于 2024-08-11 | 分类于 极客日常

近期准备开始做electron相关的开发工作,因此借着这个机会就再去了解下electron。在很久以前的文章中有稍微玩过electron+react+antd的脚手架,但也只限于快速开发electron应用,并没有去剖析整个项目结构。因此这次,还是得深入一下。

先前一段时间特别喜欢用开源的Motrix下载器,就是基于electron+vue+aria2去实现的,所以索性就把源码给clone了下来。本文就从最基础的开始,以Motrix的启动逻辑为入口,来研究下一个electron应用是如何打开的。

首先看一下Motrix的目录结构,源码基本在src下,呈现这样的层级关系:

阅读全文 »

【Hard Python】【第五章-字符串】2、re,正则表达式源码详解

发表于 2022-05-14 | 更新于 2024-04-07 | 分类于 Hard Python

正则表达式是文本处理中的重要部分,通过匹配特定的正则表达式,能够很方便地编写提取特定文本的代码。在python中,同样也已经拥有了正则表达式库re,为各位开发者提供了正则表达式的支持。

在python官方文档中,已经对正则表达式模块接口、词法和用法做了详细的介绍:

  • re——正则表达式操作
  • 正则表达式HOWTO

正则表达式常见的用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import re


def test_pattern():
pat = re.compile('[0-9]{2,3}')
print(pat.match('a'))
print(pat.match('1'))
print(pat.match('111'))


def test_matches():
s = '123abc456def789xyz007ddc'
pat = re.compile('([0-9]+)([a-z]+([0-9]+))')
for match in pat.finditer(s):
print(match.groups())


if __name__ == '__main__':
test_pattern()
test_matches()

test_pattern中,compile了一个只匹配2~3个数字字符的正则对象,test_matches中,则匹配了数字+小写字母+数字的正则对象,并且用括号分了三个组。两个函数打印出来的结果是:

1
2
3
4
5
None
None
<re.Match object; span=(0, 3), match='111'>
('123', 'abc456', '456')
('789', 'xyz007', '007')

接下来我们就深入其中,看下源码怎么实现的。

阅读全文 »

【Hard Python】【第五章-字符串】1、unicode,py3的字符串实现

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

python的字符串实质到底是什么类型的数据,这个可是困扰着很多编程者的话题。在python2我们已经被中文编码相关的问题折磨的不轻,那到了python3之后为什么又解决了这个问题呢?今天这篇文章就带大家详细剖析python3的字符串实现。

我们首先看一段代码:

1
2
3
def test_str_basic():
s = '123456789'
print(type(s))

这段代码打印了一个字符串对象的类型,其结果为<class 'str'>。str类型从哪里来?从C源码中我们可以搜索到,其来源于unicodeobject.c的PyUnicode_Type

阅读全文 »

【Hard Python】【第四章-日志】2、日志消费者Handler的实现

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

在上篇文章里说完了日志实例Logger和日志管理Manager,现在该提到Handler了。Handler是日志信息的消费者,单个Logger实例注册多个Handler,每生成一个LogRecord,就会被合法的Handler消费,在不同地方打印出日志信息。

要研究Handler,首先需要看下基类的实现:

1
2
3
4
5
6
7
8
9
10
class Handler(Filterer):
def handle(self, record):
rv = self.filter(record)
if rv:
self.acquire()
try:
self.emit(record)
finally:
self.release()
return rv

Handler会通过自带的重入锁限制日志记录被串行处理。Handler也是继承Filterer,首先会通过filter过滤日志是否满足Handler的要求,如果合法,然后调用emit方法处理日志。

emit方法在基类是NotImplemented,需要子类加以实现。因此接下来我们具体抽几个例子来看。

阅读全文 »

【Hard Python】【第四章-日志】1、Logger与Manager的源码实现

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

python语言内置了一个强大的日志模块logging,也是python内部最为复杂的功能模块之一,通过这个模块我们能够实现不同样式的日志打印。关于logging模块的官方文档也非常完备:

  • logging的用法
    • 日志常用指引
    • 日志操作手册
  • logging API
    • logging日志记录工具
    • logging config
    • logging handlers

为此,本文起我们对python的logging模块进行深入剖析,从而让大家能够更好地掌握python的logging模块。

阅读全文 »

【测试人生】用行为树做游戏自动化测试的误区

发表于 2022-04-03 | 更新于 2024-04-07 | 分类于 测试人生

在游戏自动化测试领域,行为树由于其强大的描述玩家(Agent)行为逻辑的功能,在很多场景的自动化测试都能得到应用。但是,如果对行为树的作用认识不足,很容易导致整一个自动化测试项目出现难以维护的窘境。因此,这篇文章谈一谈在游戏自动化测试里,用行为树做测试的一些误区。

阅读全文 »

【Hard Python】【第三章-GC】2、python的GC流程

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

除了通过引用计数直接销毁对象之外,python还是拥有内在GC机制的,并且也有完整的一套流程。

如果只有通过引用计数销毁对象这种机制,那么随便构造一个循环引用就会造成内存泄漏,比如下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def _dump_gc():
gcobjs = gc.get_objects()
pprint.pprint(len(gcobjs))


def test_circle():
def _test_internal():
_dump_gc()
a = []
b = []
a.append(b)
b.append(a)
_dump_gc()

_test_internal()
_dump_gc()
gc.collect()
_dump_gc()

打印出来的结果是:

1
2
3
4
13707
13709
13709
13370

很显然,当退出_test_internal作用域时,gc对象的数量没有变化,这就说明在_test_internal里创建的a、b两个对象没有被立即释放掉。如果注释掉两个append行,就能看到打印结果第三行变成了13707,说明a、b在退出函数时就被销毁了。

所以首先,我们从循环引用入手,来研究一下python的gc机制(好巧不巧的是,python的gc也是专门为循环引用而设置的)。调用gc.collect触发gc之后,会跑到gc_collect_main触发完整的gc流程。gc_collect_main是python整个gc流程的主入口,我们来看其中的代码:

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

ひかり.HDQ

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