Python中除了subprocess,还有哪些替代库可以更好地处理子进程?

系统是 win10,

我现在遇到的问题,我在 invoke 里有个 check_alive 的函数,里面是检查 我虚拟机的某个网址网页能不能访问,如果不能,那么调用 vagrant reload 重启虚拟机.

现在遇到了问题, 调用 vagrant reload 有时候会卡在那里. 所以我想想要不要添加一个超时,然后我试了几种

  1. 使用 subprocess.popen,然后 communicate 那里加 timeout 参数,没用

  2. 使用 func_timeout 库,也没有用.

今天又出现了,我尝试使用 invoke 的 run,再试试,你们有没有什么好的方法,这个调用外部命令怎么这么麻烦呢?


Python中除了subprocess,还有哪些替代库可以更好地处理子进程?

25 回复

我觉得客户端负责重启服务器,好像有点多管闲事了……这属于深度耦合啊


重启时为什么还有 communicate ?你该不会是用 subprocess 调用 sudo 了吧?
sudo 默认情况下是读 tty 的而不是读 stdin 的

这跟 subprocess 没什么关系,你得先熟悉操作系统的进程调度和管道机制,你这种需求要么就自己跑个定时后 kill 通知或直接杀掉进程

我现在的情况是这样的,我有个笔记本,一个台式.

现在打算笔记本废物利用,就把虚拟机装在笔记本上,让它每天早上一个时间重启,但是它有时候虚拟机启动不起来.
这个 check_alive 也在放在笔记本上.

这为什么跟 subrprocess 没有关系呢?

subprocess.Popen,然后再 communicate 啊,然后不是这样的吗?

我就是没看出 popen 的必要性啊。除非你 sudo 了

虚拟机起不来,你要去处理起不来的问题啊
在外围多试几次按说也并不会有什么改善吧

现在的问题是,卡住了?你不用 subprocess?那你是怎么做的呢?

但是一般而言多试几次基本就成功了啊.

贴代码

那你得想办法解决它卡住的问题啊
要么成功,要么失败,它就不该卡住

它卡住的情况下,你从外面 communicate 难道就能解决问题?

算了,跟你没得说的.

先确定卡住的原因?不一定是 subprocess 卡住,有可能是 vagrant reload 尝试重启虚拟机卡住了,你试试 加上 --force ,或者用 vboxmanage 命令直接操作 virtualbox 虚拟机。

OK,我去给 vagrant reload 添加-force 参数,关键是它不是一定出现,可能 10 天半个月没出问题,可能某天又出问题了,我先加上吧.

卡住 communicate 有超时参数的啊.超时啊.现在的问题是卡住,连超时都不告诉我好吗?

communicate timeout 会产生一个 exception 你写 try catch 了吗?

再说一遍,卡住了,卡住了,连 exception 都没有给我.

下回卡住的时候,你 strace 挂进去看看 python 和 vagrant 到底在干什么

你把 stdout/stderr 指向 subprocess.PIPE 了吗,我记得这里好像有一个坑会卡住,跟 page size 有关。

如果没特殊原因就不要 PIPE 了

page size 是什么问题啊?给个来源?

这个问题按说不至于无法 timeout 吧?

在Python中处理子进程,除了标准库的subprocess外,还有一些优秀的第三方库提供了更高层次的抽象、更安全的默认行为或更便捷的API。以下是几个主流的替代方案:

1. sh (推荐用于简单命令执行)

这是一个将系统命令作为函数调用的库,语法非常直观。

import sh
# 执行 `ls -l` 命令并获取输出
result = sh.ls("-l")
print(result)
# 支持管道:`du -sh * | sort -hr`
for line in sh.du("-sh", "*", _piped=True) | sh.sort("-hr"):
    print(line)

特点:API极其简洁,自动处理输出捕获和错误。

2. plumbum (功能全面的替代品)

提供了类似sh的语法,同时集成了本地/远程命令执行、文件路径操作等功能。

from plumbum import local
# 本地命令对象
ls = local["ls"]
# 执行并获取输出
print(ls("-l"))
# 支持重定向和管道
(ls["-l"] > "filelist.txt")()

特点:功能强大,支持命令组合、重定向和远程执行。

3. pexpect (专为交互式进程设计)

用于控制需要交互的程序(如SSH、FTP),可匹配输出并发送响应。

import pexpect
child = pexpect.spawn("ftp ftp.example.com")
child.expect("Name.*:")
child.sendline("username")
child.expect("Password:")
child.sendline("password")

特点:专门处理需要输入提示和交互的终端程序。

4. asyncsshasyncio.subprocess (异步处理)

对于需要高性能并发的场景,可使用异步方案。

import asyncio
async def run_cmd():
    proc = await asyncio.create_subprocess_shell(
        "sleep 2; echo 'Done'",
        stdout=asyncio.subprocess.PIPE
    )
    stdout, _ = await proc.communicate()
    print(stdout.decode())
asyncio.run(run_cmd())

特点:非阻塞执行,适合需要同时管理大量子进程的异步应用。

总结建议

  • 追求简洁交互:用sh
  • 需要高级功能(如远程执行):选plumbum
  • 控制交互式终端:必用pexpect
  • 构建异步应用:使用asyncio.subprocessasyncssh

总结建议:根据你的具体场景(简洁性、交互需求或异步)来选择合适的库。

回到顶部