原文链接:https://blog.csdn.net/qdPython/article/details/127689439
一、datetime函数
import datetime
(datetime.datetime.now().strftime) 是 Python 中的一个函数,它可以获取当前时间并将其格式化为字符串。具体来说,它会返回一个字符串,其中包含当前日期和时间,格式为年-月-日 时:分:秒。例如,2022-01-01 12:00:00。
strftime是一个函数,它的原意是"string format time",即将时间以字符串的形式输出,用于时间格式的转换。该函数通常用于将时间戳转换为指定格式的字符串,也可以将字符串转换为时间戳。在不同编程语言中,该函数可能会有略微不同的用法和参数。
二、logging和logging.handlers
https://blog.csdn.net/mouday/article/details/80760343
Logger:日志记录器,是应用程序中可以直接使用的接口。
Handler:日志处理器,用以表明将日志保存到什么地方以及保存多久。
Formatter:格式化,用以配置日志的输出格式
上述三者的关系是:一个 Logger 使用一个 Handler,一个 Handler 使用一个 Formatter。
第2行 解释:
log重定向到log.txt文件中,
文件格式就是 时间+具体的消息
文件模式是可写的
第3行:
通过getLogger获取一个log对象
__name__就是把这个模块给传进去
第4行:
设置日志层级,设置为debug模式
第5行开始就是:
5个输出语句
运行:
注释设置的日志级别 logger设置的默认就是warning
查看log.txt
之前的debug 和 info就没没有被执行了
引入log的handlers模块
如果想在控制台输出且输出到日志。可以设置一个更低级别的handler对象
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
第2行:初始化一个log对象
第三行:streamHandler是标准输出
第四行:输出到文件
第5、6、7分别给logger对象、两个handlers分别设置log级别
也就是想屏幕输出是waring 文件是debug
8\9行就是设置下日志格式
然后把两个handlers通过addHandler添加到logger对象中去
最后就是5个测试的log信息
运行:
当日志文件过大的时候 不利于查看+备份 所以更改为文件字节只要大于500就重新生成一个文件 文件总数为3 当数量>3就会冲掉第一个文件的内容
增加日志内容
可以看到生成了3个文件
除了按照文件大小分割还有按照时间分割。
next vedio
代表连接上了
pycharm链接ssh服务器
三、subprocess模块
subprocess允许你在python的当前进程中产生一个子进程来运行其他程序,例如在python中调用一些linux指令。或者利用subprocess在python中去调用图形界面程序。
可以看到返回了date结果
打印process的时候包含了一个CompletedProcess的对象,其中还包含一个返回状态码
状态码为0则代表程序调用成功
注意在run函数中 多个参数 需要指定为多个token 不能直接用字符串 date -y这种。故意输出一个错误的指令
如果觉得分割很麻烦 可以使用shlex模块
如果希望告诉python这一行执行失败就跳出错误而不是继续运行去返回Completed,可以设置check=True
我的代码需要返回Completed所以check=False 默认就是
check: 如果check参数的值是True,且执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常,且该异常对象会包含 参数、退出状态码、以及stdout和stderr(如果它们有被捕获的话)。
字符写错
subprocess.run()函数是Python3.5中新增的一个高级函数,其返回值是一个subprocess.CompletedPorcess类的实例,因此,subprocess.completedPorcess类也是Python 3.5中才存在的。它表示的是一个已结束进程的状态信息,它所包含的属性如下:
args: 用于加载该进程的参数,这可能是一个列表或一个字符串
returncode: 子进程的退出状态码。通常情况下,退出状态码为0则表示进程成功运行了;一个负值-N表示这个子进程被信号N终止了
stdout: 从子进程捕获的stdout。这通常是一个字节序列,如果run()函数被调用时指定universal_newlines=True,则该属性值是一个字符串。如果run()函数被调用时指定stderr=subprocess.STDOUT,那么stdout和stderr将会被整合到这一个属性中,且stderr将会为None
stderr: 从子进程捕获的stderr。它的值与stdout一样,是一个字节序列或一个字符串。如果stderr没有被捕获的话,它的值就为None
check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。
实例
subprocess.run()
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
https://blog.csdn.net/qq_43331089/article/details/124421661
【Python】python之subprocess模块详解
四、asyncio
五、from concurrent.futures import ThreadPoolExecutor
concurrent.futures提供一个异步的,多线程
主要有2个接口 ThredPoolExecutor和ProcessPoolExecutor
主要是通过类extractor调用函数的
字符串转数组
本文链接:https://blog.csdn.net/fengqianlang/article/details/127256725
Python异步编程 asyncio
1、
2、协程
计算机只提供了线程和进程
协程不是计算机提供的,程序员认为创造
就是微线程–就是一个线程来回在代码中切换游走的线程
正常的逻辑就是执行完func1后再执行func2
协程就会在2个函数间游走。再func1里面执行print(1)后切换到func2执行print(3) 然后再切换去fun1
协程就是人为控制在函数中间来回切换 注意一个线程来回切换(协程就是来回切换)
实现协程的方法:
1.1 、greenlet 第三方模块
实现了在多个函数中来回切换
1.2 、yield 关键字实现
如果一个函数里面存在yield 我们就认为是一个生成器函数
只要执行这个函数 返回的就是一个生成器
所以f1=func1()
就是生成了f1这个生成器
循环f1其实就是执行fun1()的一行yield
所以第一次循环就是返回print(yield 1)
第二次循环就是执行yield from func2() 就是跳到fun2函数中了
所以执行yield 3打印出3 然后继续执行yield4打印4
下次循环就是执行fun1()里面的yield 2打印的就是2了
1、3、4、2
1.3、asyncio模块–官方的内置模块
必须是python3.4以及之后版本才可以使用
coroutine协程
fun1是普通函数 但是被@asyncio装饰后就变成了协程函数
协程函数无法直接通过调用func1()去执行
必须这样才可以执行协程函数:
但是这样就只执行嘞func1()函数
使用ensure_future封装下两个协程函数 然后写到task列表中
这样就会帮我们同时去执行这两个函数
比如随机先执行嘞fun1 打印了print(1)后遇到了asyncio.sleep遇到io耗时会等待2秒 但是 不会安静的等待 而是去执行其他的tasks中的任务
然后去fun2执行print(3) 然后func1的io等待已经完成了 继续去fun1执行
1、3、2、4
这个比较牛逼 就是遇到io阻塞会自动切换 上面两种方法是手动的 不会
把sleep更换为下载图片
再print(1)后图片下载需要请求服务器返回 这个等待过程去执行第二个函数 也就是发了请求没等服务器响应回来先去执行第二个函数
去第二个函数也发起了图片下载的请求。然后相当于花费了2秒。2个函数的图片都下载下来了
1.4 asyncio & await 关键字
python3.5及以后
为了代码的简洁就用了这个关键字
区别就是把装饰器更改为async 把yield from更改为await
三、协程的意义
下载的时候会一张一张下载
上面的下载用的是requets模块
现在协程的下载用到的是aiohttp模块 需要下载
会发现请求同时发出 结果几乎同时返回
同步:排队一个一个执行(request)
异步:一个任务发出去不等待结果继续发送下一个请求 (协程)
四、基于协程的异步编程
4.1 事件循环
五、asyncio 高潮环节
六、await
中间等待可以去执行别的函数了
注意 func()里面的await 必须有返回值了 才会继续执行后面的部分 所以只能等待other()执行完成返回值
遇到io会执行其他的函数 但是不会往别的io后面继续走
这里的感觉就是串型的感觉
七、task对象
并发调度协程
关键就是 创建完task对象,将当前func任务立即!!添加到事件循环
比如遇到io切换就会立即去切换到func任务去执行
所以这个和上一个的区别就是task1执行后遇到io会立刻执行task2的func 因为他已经在func任务并且是就绪的状态了
所以事件循环列表里就是 第一个是main 然后是2个func()任务 都是等待被执行
这个事例很少 理解即可
下面的重点学习 上面创建两个task这里更改为列表
这里执行完会返回两个值 分别是done、pending
就是一个元祖
done有意义
done是个集合,任务的返回值都会放在done中
这里pending简单介绍下 如果在task_list后面加上timeout=1那么等待任务超过1s的就不会被继续执行了 这些任务会放到pending中 一般timeout=None
这里的ret1 ret2删了
可以看到done是个集合
可以看到默认的task名字叫做Task-2了
这里task任务写在了协程函数里面
也就是说 先创建了loop事件循环已经创建 执行到携程函数的创建task任务才会加任务到事件循环列表中去
那么task任务创建任务想要在loop(asynio.run创建loop)之前需要怎么处理??
所以更改task_list 里面为协程对象即可
所以就是asyncio.run(协程对象)
在asyncio.run内部会帮我们创建task任务
也就是在生成事件循环后才会创建 这样就没问题了
所以如果task想写在函数外面就得这样子了
其实本质和写个函数放到里面一样的
task对象是什么??–帮助我们立即将某个任务放到事件循环,也就是帮我们在事件循环里面并发创建多个任务,让遇到事件io自由处理
八、asyncio.future对象
更底层
是task类的基类 也就是task里面的一些功能是future提供的
是一个更低级的接口 帮助我们等待异步的结果
也就是await等结果的底层其实就是future实现的
内部有个state来判断状态
这个函数执行了会一直等待…
创建task就会给事件循环放一个就绪的任务
放到任务就是给事件循环列表里面放set_after(fut)函数–等待别执行 只要当前线程遇到await就执行
所以继续向下执行 遇到了data = await fut
所以就会去执行刚才放到队列的set_after(fut)函数
所以先等待2秒
await fut还没有返回值
所以继续执行set_after(fut)函数后面的部分
给fut对象去设置666
所以future就是帮我们等待结果
为什么task不会夯住?
因为创建task的时候一般我们都会给里面写一个函数,就会帮我们绑定一个函数/任务
当任务执行完成后会帮自动set result
也就不再等待了
八、corrent的异步对象
这里是另外的一个future的对象
这个是concurrent.future future对象
和上面的future没有关系!!
这个是以后想用进程池/线程池 来实现异步操作用到的对象
也是用来获取结果的
pool.submit 的意思就是让你拿一个线程 去执行这个fun函数
虽热这里十个循环会创建十个任务,线程池定义最多有五个线程,也就是只能最多并发五个,
其实会一起执行
每次往线程池提交了任务后,他就会返回一个fut这个future对象,这个最开始执行完submit这条命令是没有结果的,
当在pool执行完成后才会把值赋值给fut
所以这个future是使用线程池、进程池实现异步操作时用的对象
前面的是协程
相同点:都是用来等待结果
代码可能会用协程(asyncio)和线程池(concurrent)交叉使用:
比如mysql不支持使用协程的asyncio 以及 await操作
如果代码里面的第三方模块不支持协程,就会借助线程、进程做异步编程。
协程函数 这里用于获取当前事件循环
这一步操作会默认有两步骤:创建一个线程池,把func1函数放进去,如果放在线程池返回的就是一个future对象
但是这个future对象和协程异步的future对象不一样。所以这里需要把corrent.futures的Future转换为协程的future对象
所以第二步就是转换 把corrent.futures的Future转换为协程的future对象
这个时候也就有await功能了
所以这样就既支持了异步的操作,又让内部通过线程做成了线程的异步的操作–也就是结合了
这里面的None。默认创建的是线程池,
这里创建完线程池后 把池加到第一个参数了。就跟上面的例子一样。
这里再贴一下协程异步的future对象