python进阶笔记之os库与装饰器

本文介绍了Python中如何使用os.system和subprocess库调用外部程序,包括命令执行、参数传递和非阻塞调用。同时,详细阐述了装饰器的概念和实现方式,展示了如何通过装饰器给函数添加新功能,以及如何处理带参数的装饰器。内容覆盖了程序控制和函数增强,适合Python初学者和进阶者阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pycharm调用外部程序

应用场景:当公司项目成熟的时候,python代码会运行在 项目服务器上,需要对服务器进行一些操作,比如获取服务器的ip地址等信息,此时就需要用到如下库实现
有两种方法可以实现:os.system方法调用,subprocess库

  • os.system
    方法解释:等于打开操作系统的shell,敲入一串命令,比如ipconfig命令
    在这里插入图片描述
import os
# 在shell终端 输入ipconfig
os.system('ipconfig')
print("after call")

# 在shell终端 打开 画图板
os.system('mspaint')

# 在shell终端进入 cmd工具
os.system('cmd.exe')
#在cmd命令行输入退出
os.system('exit')

操作问题:如果运行后乱码,需要在setting的file coding修改编码utf-8为GBK
在这里插入图片描述
阻塞式调用:调用外部程序如cmd.exe、系统的mspaint画板等时,如果没有主动退出,则python程序会一直停在那里,只有手动退出了,才会执行后面的代码
组装复杂参数
在这里插入图片描述

os.system("for %i in (1, 2, 10) do @echo %i")

返回值:判断命令是否执行成功,如果执行成功,这个命令的返回值是0
命令执行失败会报错,返回值等于1
在这里插入图片描述

  • subprocess
    该库的check_output方法,可以实现调用外部程序,返回值就是执行结果,是byte类型,需要编码一下,可以使用utf-8,如果不行换用gbk编码(但是注意:需要等到被调用程序退出时才会有返回值)
    在这里插入图片描述
    该库的Popen类:①调用时会自动打印其输出的信息,②非阻塞式调用,在被调用程序运行时不会阻塞后面的代码,可以继续执行后面的代码。③且该函数在运行时,可以输入一些信息给被调用的程序
    在这里插入图片描述
    将Popen类赋值给一个对象,Popen的输出本来是直接打印在终端的,但是使用communicate方法将打印的标准输入重定向给了一个 返回值。
    在这里插入图片描述
    在这里插入图片描述

装饰器

装饰器组成: 自定义函数+ @函数
装饰器作用:使得执行到原函数时,不会执行原函数里得代码,而是转为执行装饰器新建得函数代码(起到了重新构造函数的效果)
学前理解:在讲解装饰器时,先熟悉一个概念:函数foo() 可以作为返回值,如 return foo。此时外层函数的返回值就是一个内部的函数foo,如果要实现内部函数的功能,需要调用外层函数然后加()继续调用foo 函数实现

def f():
	print("888888")
	def foo():
		print("这是内部函数的内容")
	return foo		# 返回内部函数,但不调用

f()		#调用外部函数,得到的返回值是一个函数foo
f()()   #调用外部函数,得到foo,继续调用foo(),得到foo的调用结果

而装饰器,就是根据这一点来 实现,将 新加功能的函数 当成一个参数返回,当调用外部函数时,在后面加上() 就可以实现 内部函数的调用

1、装饰器引入:当需要 给函数进行新增功能时,可以将 已定义的函数,作为参数传递给另一个新函数如

def foo():
	print("执行一系列接口测试")
	time.sleep(1)
	
def bar(func):
	startTime = time.yime
	func()		#调用该原有函数
	endTime = time.time
	print("总计时:",endTime- startTime)

#开始调用自己新建的函数,并把原有函数当作参数传入
bar(foo)

2、装饰器完善:但是!当其他 同事想拥有这个新功能时,就需要调用我自定义的新函数bar,而无法直接用foo函数实现。
所以,需要实现: 同事用到的foo函数,实际就是我定义的新函数bar;即foo() == bar(foo)
修改代码实现:将 新定义的函数操作内容,封装成一个inner函数,然后外层bar函数 直接返回inner函数(即实现inner函数的结果,会通过bar函数调用返回)

def foo():
	print("执行一系列接口测试")
	time.sleep(1)
	
def bar(func):
 	def inner():
		startTime = time.yime
		func()		#调用该原有函数
		endTime = time.time
		print("总计时:",endTime- startTime)		

此时,如果同事在使用时,先将我新建的函数赋值给foo,然后调用foo(),即可实现不改自己代码,也能有用到新加的功能

foo = bar(foo)		# 同事使用时,额外需要 将自己定义的函数bar直接 赋值给foo

这个时候,同事每次用到foo,即foo() 时,相当于 bar(foo)(),调用了内部函数inner
3、装饰器优化
由于同事在使用时,都需要自己去定义赋值,所以python引入了语法行:@,@bar 表示bar是一个装饰器,且定义 foo = bar(foo)。
运行流程:先定义@bar,后续代码进行到foo() 时,不会执行foo()里面的代码,而是去执行装饰器里的代码

# 我给前同事的功能新加了功能
def bar(func):
    def inner():
        start_time = time.time()
        func()  # 调用该原有函数
        end_time = time.time()
        print("总计时:", end_time - start_time)
    return inner

@bar
#前同事写的功能函数
def foo():
    print("执行一系列接口测试")
    time.sleep(1)
    
# 后同事开始 按照计划调用foo函数,此时的foo已经是bar(foo)了
foo()

4、带参的装饰器
如果原函数foo() 是一个带参的函数,则在定义装饰器的时候,需要将入参 定义在inner函数处,此时,inner里面调用原foo() 函数时,可以给foo传参
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值