Linux python Popen报错:FileNotFoundError: [Errno 2] No such file or directory & kill() 后进程仍然运行

遇到一个坑

   从 window 环境的 Popen 复制粘贴到 Linux 使用,竟然无法使用,报错 No such file or directory ,把我搞郁闷了,完全一样的 code,怎么 linux 上就找不到文件了?

   原来,linux 上 Popen 使用字符串命令,Popen 需要加上一个参数 shell=True

报错

Traceback (most recent call last):
  File "case.py", line 138, in <module>
    __tl.do_test()
  File "case.py", line 119, in do_test
    tp.start()
  File "case.py", line 65, in start
    self.__proc = Popen(self.__cmd)
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'python do_test.py 3'

官方文档

args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.

If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory. However, note that Python itself offers implementations of many shell-like features (in particular, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), and shutil).

第二个大坑

   如上面官方文档所述,如果 shell=True ,那么会通过 shell 来启动进程。这意味着,一次 Popen 会启动两个进程,一个 shell 进程,一个命令进程。然后 Popen 返回的 pid 是 shell 进程的 pid,这会导致 Popen.kill() 等函数不起作用,进程还在正常运行,所以一定要使用参数列表的形式启动,不要通过命令行的形式,不要使用 shell=True

第三个坑

   上面虽然解决了 kill() 不掉真实进程的问题,但是还有一坑。如何把一个命令行字符串转换成 list[str] ,使用 str.split() ?这是不行的,如果命令行里有引号之类的就会有问题。自己实现一个函数?可以,不过自己写的总是怕考虑不全的地方。好在 python 官方有词法分析器的库 shlex ,只需要 shlex.split() 就可以获得我们想要的格式了,Python Library - shlex

参考

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误通常是因为系统无法找到 FFmpeg 可执行文件导致的。您需要确保已经正确安装了 FFmpeg 并将其添加到系统的 PATH 环境变量中。 如果您已经安装了 FFmpeg 但仍然遇到此错误,可以尝试在代码中指定 FFmpeg 可执行文件的路径。例如,假设您已经将 FFmpeg 安装在 `C:\ffmpeg\bin` 目录下,您可以使用以下代码来指定 FFmpeg 的路径: ```python import os import cv2 import subprocess # 指定 FFmpeg 可执行文件的路径 ffmpeg_path = "C:/ffmpeg/bin/ffmpeg.exe" if not os.path.isfile(ffmpeg_path): raise FileNotFoundError("FFmpeg not found at: " + ffmpeg_path) # 打开 RTMP 推流进程 rtmp_url = "rtmp://your_rtmp_server_url" command = [ffmpeg_path, '-y', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-s', '640x480', '-i', '-', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'ultrafast', '-f', 'flv', rtmp_url] proc = subprocess.Popen(command, stdin=subprocess.PIPE) # 打开摄像头并捕获实时视频流 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break # 将视频帧写入 RTMP 推流进程 proc.stdin.write(frame.tostring()) # 显示视频帧 cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # 关闭摄像头和 RTMP 推流进程 cap.release() cv2.destroyAllWindows() proc.stdin.close() proc.wait() ``` 在上面的代码中,我们添加了一个 `ffmpeg_path` 变量来指定 FFmpeg 可执行文件的路径。然后,我们检查该文件是否存在,并在启动 FFmpeg 进程时使用该路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值