Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python 异步: 在非阻塞子进程中运行命令(19)

Python 异步: 在非阻塞子进程中运行命令(19)

作者头像
数据科学工厂
发布于 2023-03-21 01:57:06
发布于 2023-03-21 01:57:06
3.3K00
代码可运行
举报
运行总次数:0
代码可运行

我们可以从 asyncio 执行命令。该命令将在我们可以使用非阻塞 I/O 写入和读取的子进程中运行。

1. 什么是 asyncio.subprocess.Process

asyncio.subprocess.Process 类提供了由 asyncio 运行的子进程的表示。它在 asyncio 程序中提供子进程的句柄,允许对其执行操作,例如等待和终止它。

API 与 multiprocessing.Process 类非常相似,可能与 subprocess.Popen 类更相似。具体来说,它与 subprocess.Popen 共享 wait()、communicate() 和 send_signal() 等方法以及 stdin、stdout 和 stderr 等属性。

现在我们知道了 asyncio.subprocess.Process 类是什么,让我们看看如何在我们的 asyncio 程序中使用它。

我们不直接创建 asyncio.subprocess.Process。相反,在 asyncio 程序中执行子进程时,会为我们创建一个类的实例。

有两种方法可以将外部程序作为子流程执行并获取 Process 实例,它们是:

  • asyncio.create_subprocess_exec() 用于直接运行命令。
  • asyncio.create_subprocess_shell() 用于通过 shell 运行命令。

让我们依次看一下每个示例。

2. 如何直接运行命令

命令是在命令行(终端或命令提示符)上执行的程序。这是另一个直接运行的程序。

Linux 和 macOS 上的常见示例可能是:

  • ‘ls’ 列出目录的内容
  • ‘cat’报告文件的内容
  • “data”报告日期
  • ‘echo’ 报告一个字符串
  • ‘sleep’ 睡眠几秒钟

我们可以通过 create_subprocess_exec() 函数从 asyncio 程序执行命令。

asyncio.create_subprocess_exec() 函数接受一个命令并直接执行它。

这很有用,因为它允许命令在子进程中执行,并允许 asyncio 协程读取、写入和等待它。

与 asyncio.create_subprocess_shell() 函数不同,asyncio.create_subprocess_exec() 不会使用 shell 执行命令。

这意味着 shell 提供的功能,例如 shell 变量、脚本和通配符,在执行命令时不可用。

这也意味着执行命令可能更安全,因为没有机会进行 shell 注入。

现在我们知道了 asyncio.create_subprocess_exec() 的作用,让我们看看如何使用它。

2.1. 如何使用 Asyncio create_subprocess_exec()

asyncio.create_subprocess_exec() 函数将在子进程中执行给定的字符串命令。

它返回一个代表子进程的 asyncio.subprocess.Process 对象。

create_subprocess_exec() 函数是一个协程,这意味着我们必须等待它。它会在子流程启动后返回,而不是在子流程完成时返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# execute a command in a subprocess
process = await asyncio.create_subprocess_exec('ls')

正在执行的命令的参数必须作为后续参数提供给 create_subprocess_exec() 函数。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# execute a command with arguments in a subprocess
process = await asyncio.create_subprocess_exec('ls', '-l')

我们可以通过等待 wait() 方法来等待子进程完成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# wait for the subprocess to terminate
await process.wait()

我们可以通过调用 terminate() 或 kill() 方法直接停止子进程,这将在子进程中引发一个信号。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# terminate the subprocess
process.terminate()

命令的输入和输出将由 stdin、stderr 和 stdout 处理。我们可以让 asyncio 程序处理子进程的输入或输出。

这可以通过指定输入或输出流并指定要重定向的常量来实现,例如 asyncio.subprocess.PIPE。

例如,我们可以将命令的输出重定向到 asyncio 程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# start a subprocess and redirect output
process = await asyncio.create_subprocess_exec('ls', stdout=asyncio.subprocess.PIPE)

然后我们可以通过 asyncio.subprocess.Process 实例通过 communicate() 方法读取程序的输出。

此方法是协程,必须等待。它用于通过子流程发送和接收数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# read data from the subprocess
line = process.communicate()

我们还可以通过以字节为单位设置“input”参数,通过 communicate() 方法将数据发送到子进程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# start a subprocess and redirect input
process = await asyncio.create_subprocess_exec('ls', stdin=asyncio.subprocess.PIPE)
# send data to the subprocess
process.communicate(input=b'Hello\n')

在后台,asyncio.subprocess.PIPE 将子进程配置为指向 StreamReader 或 StreamWriter,用于向子进程发送数据或从子进程发送数据,并且 communicate() 方法将从配置的读取器读取或写入字节。

我们可以通过子进程通过 stdin、stdout 和 stderr 属性直接与 StreamReader 或 StreamWriter 交互。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# read a line from the subprocess output stream
line = await process.stdout.readline()

现在我们知道如何使用 create_subprocess_exec() 函数,让我们看一些工作示例。

2.2. Asyncio create_subprocess_exec() 示例

我们可以探索如何在 asyncio 的子进程中运行命令。在这个例子中,我们将执行“echo”命令来报告一个字符串。

echo 命令将直接在标准输出上报告提供的字符串。下面列出了完整的示例。

请注意,此示例假设您可以访问“echo”命令,我不确定它是否适用于 Windows

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# SuperFastPython.com
# example of executing a command as a subprocess with asyncio
import asyncio
 
# main coroutine
async def main():
    # start executing a command in a subprocess
    process = await asyncio.create_subprocess_exec('echo', 'Hello World')
    # report the details of the subprocess
    print(f'subprocess: {process}')
 
# entry point
asyncio.run(main())

运行示例首先创建 main() 协程并将其作为 asyncio 程序的入口点执行。

main() 协程运行并调用 create_subprocess_exec() 函数来执行命令。

main() 协程在创建子进程时挂起。返回一个 Process 实例。

main() 协程恢复并报告子进程的详细信息。 main() 进程终止,asyncio 程序终止。

echo 命令的输出在命令行上报告。这突出了我们如何从 asyncio 程序执行命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Hello World
subprocess: <Process 50249>

3. 如何通过 Shell 运行命令

我们可以使用 shell 执行命令。shell 是命令行的用户界面,称为命令行解释器 (CLI)。它将代表用户解释和执行命令。

它还提供诸如用于脚本、通配符、管道、shell 变量(例如 PATH)等的原始编程语言等功能。

例如,我们可以将一条命令的输出重定向为另一条命令的输入,比如将“/etc/services”文件的内容重定向到word count命令“wc”中,统计行数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cat /etc/services | wc -l

基于 Unix 的操作系统中的 shell 示例包括:

shell 已经在运行,它被用来启动 Python 程序。您无需执行任何特殊操作即可获取或访问 shell。

我们可以通过 create_subprocess_shell() 函数从 asyncio 程序执行命令。

asyncio.create_subprocess_shell() 函数接受一个命令并使用当前用户 shell 执行它。

这很有用,因为它不仅允许执行命令,还允许使用 shell 的功能,例如重定向、通配符等。

该命令将在执行 asyncio 程序的进程的子进程中执行。重要的是,asyncio 程序能够与子进程异步交互,例如通过协程。

通过 shell 而不是直接执行命令时,可能会有安全考虑。

这是因为请求执行命令和正在执行的命令之间至少存在一层间接和解释,允许可能的恶意注入。

现在我们知道了 asyncio.create_subprocess_shell() 的作用,让我们看看如何使用它。

3.1. 如何使用 Asyncio create_subprocess_shell()

asyncio.create_subprocess_shell() 函数将通过当前 shell 执行给定的字符串命令。

它返回一个表示进程的 asyncio.subprocess.Process 对象。

它与我们在上一节中看到的 create_subprocess_shell() 函数非常相似。不过,我们将回顾如何使用该函数以及如何通过 Process 实例与流程交互(以防您直接跳到本节)。

create_subprocess_shell() 函数是一个协程,这意味着我们必须等待它。它会在子流程启动后返回,而不是在子流程完成时返回。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# start a subprocess
process = await asyncio.create_subprocess_shell('ls')

我们可以通过等待 wait() 方法来等待子进程完成。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# wait for the subprocess to terminate
await process.wait()

我们可以通过调用 terminate() 或 kill() 方法直接停止子进程,这将在子进程中引发一个信号。

命令的输入和输出将由 shell 处理,例如标准输入、标准错误和标准输出。

我们可以让 asyncio 程序处理子进程的输入或输出。

这可以通过指定输入或输出流并指定要重定向的常量来实现,例如 asyncio.subprocess.PIPE。

例如,我们可以将命令的输出重定向到 asyncio 程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# start a subprocess and redirect output
process = await asyncio.create_subprocess_shell('ls', stdout=asyncio.subprocess.PIPE)

然后我们可以通过 asyncio.subprocess.Process 实例通过 communicate() 方法读取程序的输出。

此方法是协程,必须等待。它用于通过子流程发送和接收数据。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# read data from the subprocess
line = process.communicate()

我们还可以通过以字节为单位设置“input”参数,通过 communicate() 方法将数据发送到子进程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# start a subprocess and redirect input
process = await asyncio.create_subprocess_shell('ls', stdin=asyncio.subprocess.PIPE)
# send data to the subprocess
process.communicate(input=b'Hello\n')

在后台,asyncio.subprocess.PIPE 将子进程配置为指向 StreamReader 或 StreamWriter,用于向子进程发送数据或从子进程发送数据,并且 communicate() 方法将从配置的读取器读取或写入字节。

我们可以通过子进程通过 stdin、stdout 和 stderr 属性直接与 StreamReader 或 StreamWriter 交互。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
# read a line from the subprocess output stream
line = await process.stdout.readline()

现在我们知道如何使用 create_subprocess_shell() 函数,让我们看一些工作示例。

3.2. Asyncio create_subprocess_shell() 示例

我们可以探索如何使用 shell 在 asyncio 的子进程中运行命令。在这个例子中,我们将执行“echo”命令来报告一个字符串。

echo 命令将直接在标准输出上报告提供的字符串。下面列出了完整的示例。

请注意,此示例假设您可以访问“echo”命令,我不确定它是否适用于 Windows。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# SuperFastPython.com
# example of executing a shell command as a subprocess with asyncio
import asyncio
 
# main coroutine
async def main():
    # start executing a shell command in a subprocess
    process = await asyncio.create_subprocess_shell('echo Hello World')
    # report the details of the subprocess
    print(f'subprocess: {process}')
 
# entry point
asyncio.run(main())

运行示例首先创建 main() 协程并将其作为 asyncio 程序的入口点执行。main() 协程运行并调用 create_subprocess_shell() 函数来执行命令。

main() 协程运行并调用 create_subprocess_shell() 函数来执行命令。main() 协程恢复并报告子进程的详细信息。 main() 进程终止,asyncio 程序终止。

echo 命令的输出在命令行上报告。这突出显示了我们如何使用 shell 从 asyncio 程序执行命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
subprocess: <Process 43916>
Hello World
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 冷冻工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
python3--基础数据类型
切片就是通过索引(索引:索引:步长)截取字符串的一段,形成新的字符串(原则就是顾头不顾尾)
py3study
2018/08/02
5110
Python基础之str常用方法、for循环
还有一个方法index,它和find作用类似,通过元素找索引,不同点是:找不到指定的字符则会报错!
孙晨c
2019/09/10
8810
Python全栈学习_day003知识点
今日大纲: 1. 基础数据类型 总览 2. int 3. bool 4. str 5. for循环 1. 基础数据类型 总览   int: 用于计算,计数等 str:'这些内容',用户少量数据的存储,便于操作 bool:True, False,两种状态,机器反馈给用户的对/错 list:[1, 'k', True, [], (), {}, ...] 大量的数据,各种数据类型,操作方便 tuple:(1, 'k', True, [], (), {}, ...) 只读列表
py3study
2020/01/20
4220
python 基础知识第3讲:基本数据类型
表达式是由数据、算符、数字分组符号()、自由变量和约束变量等以能求得数值的有意义的排列方法所得的组合(类似于数学的公式)。
小海怪的互联网
2019/08/23
5040
python3--基础综合测试
解释:char类型在python中不存在,它是其他编程语言的一种数据类型,比如C/C++,JAVA
py3study
2018/08/02
1.2K0
python练习题-day3
16)从name变量对应的值中找到"N"对应的索引(如果找不到则报错),并输出结果
10JQKA
2019/10/23
7380
万恶之源 - Python基础数据类型一
在32位机器上int的范围是:  -2**31~2**31-1,即-2147483648~2147483647
py3study
2020/01/19
1.2K0
python基础之数据类型与变量
一.变量 1 什么是变量之声明变量 #变量名=变量值 age=18 gender1='male' gender2='female' 2 为什么要有变量 变量作用:“变”=>变化,“量”=>计量/保存状态 程序的运行本质是一系列状态的变化,变量的目的就是用来保存状态,变量值的变化就构成了程序运行的不同结果。 3 变量值之类型与对象 程序中需要处理的状态很多,于是有了不同类型的变量值,x='seven',变量值'seven'存放与内存中,绑定一个名字x,变量值即我们要存储的数据。 在python中所有数据都是
用户1214487
2018/01/23
9730
6-2、Python 数据类型-字符串
name =“abcdefABCDEF"如何取出ced值? name逆序输出,怎么办?
度假的小鱼
2023/11/07
2050
6-2、Python 数据类型-字符串
python之路-基础篇5
1、字符串常用操作 #字符串操作 name = "my name is kk" print(name.capitalize())   #>>>My name is kk #capitalize()  #首字母大写 print(name.count("a")) #>>>1 #count("a")  统计有多少个a print(name.center(50,"-")) #>>>------------------my name is kk------------------- #center(50,"-"
py3study
2020/01/15
3460
python的基本数据类型(一)
一.运算符 逻辑运算 and:两边都真则真 or:有真则真 not:非假是真 顺序:()>==>not==>and>=or 二.while.. else while 条件: 代码块 else: 当条件为假的时候执行 三.主要内容 1.编码 1.最早的计算机编码是ASCII,美国人创建的,包含了英文字母(大小写字母). 数字. 标点等特殊符号+-*/$& 128个码位 2**7 在此基础上加上了一位 2**8 2.GBK 国标码 16位.2个直接(双字节字
py3study
2020/01/17
4390
python基础数据类型----整数 ,
s = input('输入内容') #input输入的为字符串类型 if s: #(字符串作为布尔值进行判断) print('有内容') else: print('没有输入任何内容') #直接回车,显示“没有输入任何内容” #先空格,再回车,显示“有内容”
py3study
2020/01/16
8750
Python学习笔记_Day01
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qA8upgBq-1584409255959)(C:\Users\daiyajie\AppData\Roaming\Typora\typora-user-images\1584352090231.png)]
非著名运维
2022/06/22
4690
Python学习笔记_Day01
Python开发基础-day2
    acclist.insert()  (要插入的位置,插入的内容)  list插入内容
py3study
2020/01/15
5260
一、python学习笔记-基本数据类型-字符串(二)
其他字符串操作 # 其他字符串操作 # 单引号双引号用法 """ 1、字符串中有单引号,使用双引号 2、字符串中有双引号,使用单引号 3、字符串中有既有单引号又有双引号,使用三引号 """ str1 = "Let' Go" print(str1) str2 = 'My name is "abc"' print(str2) str3 = '''My name is "abc". Let' Go''' print(str3) # 乘号 """ 1、重复多少次 """ str4 = 'hello' pri
堕落飞鸟
2022/01/11
2770
python 字符串所有操作
使用type获取创建对象的类 type(name) 使用dir获取类的成员dir(name) 使用vars获取类的成员和各个成员的值
用户7886150
2021/01/10
3440
Python基础核心概念(1)
字符串就是一系列字符。在Python中,用引号括起的都是字符串,其中引号包括单引号和双引号。这种灵活性能够在字符串中包含引号和撇号,如:
用户9925864
2022/07/27
5690
Python基础核心概念(1)
python中string.ascii_letters是什么-Python 字符串常用方法总结
name.find('x') 找到这个字符返回下标,多个时返回第一个;不存在的字符返回-1
用户7886150
2021/01/27
3.1K0
「Python」字符串操作
在 Python 程序中,如果我们把单个或多个字符用单引号或者双引号包围起来,就可以表示一个字符串。
AXYZdong
2021/12/07
5500
python之路,Python基础篇2(
一、.pyc是个什么鬼: pyc文件其实是PyCodeObject的一种持久化保存方式。 二、数据类型 1、数字: 2 是一个整数的例子。 长整数 不过是大一些的整数。 3.23和52.3E-4是浮点数的例子。E标记表示10的幂。在这里,52.3E-4表示52.3 * 10-4。 (-5+4j)和(2.3-4.6j)是复数的例子,其中-5,4为实数,j为虚数,数学中表示复数是什么? int(整型)   在32位机器上,整数的位数为32位,取值范围为-2**31~2**31-1,即-21474
py3study
2020/01/10
8180
相关推荐
python3--基础数据类型
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验