将 Python 子进程输出从字符串转换为 int 或 float

Convert Python subprocess output from string to int or float

我正在尝试使用 this command but from a python script using the subprocess module. The output of the command is in string but since the frame count of a video is an integer I would like to have it as an int object in python. However, int() as shown here 读取视频的帧,但没有按预期工作,因为我假设我会得到 321 作为整数。

终端输出:

ValueError: invalid literal for int() with base 10: ''

我尝试过 here 的解决方案,例如 float(),但它们对我不起作用。

代码:

import subprocess

def main():
    shell_ffprobe_frame_count = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-count_packets",    "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", "test.mkv"]
    output = subprocess.Popen(shell_ffprobe_frame_count, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)

    print(output.stdout.read()) # 321
    print(type(output.stdout.read())) # <class 'str'>

    print(int(output.stdout.read())) # should be '321'
    print(type(int(output.stdout.read()))) # should be 'int'

if __name__ == "__main__":
    main()

我从子进程中得到了 <class 'str'> 作为 return 类型,这是我以前从未见过的。 type('321') 在我的终端中只生成 str。我不明白其中的区别,我敢打赌这就是错误的原因。感谢任何帮助。

您对 output.stdout.read() 的第一次调用消耗了该过程的所有输出;所有后续读取 return 空字符串(表示文件结束)。输出一次 ,将其存储在一个变量中,并对存储的字符串执行测试:

import subprocess

def main():
    shell_ffprobe_frame_count = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-count_packets",    "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", "test.mkv"]
    output = subprocess.Popen(shell_ffprobe_frame_count, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)

    outdata = output.stdout.read()
    print(outdata) # 321
    print(type(outdata)) # <class 'str'>

    print(int(outdata)) # should be 321
    print(type(int(outdata))) # should be 'int'

if __name__ == "__main__":
    main()

<class 'str'> 输出就是 str class 本身的表示方式,这是打印任何 strtype 时应该期望的结果值。

或者,既然你似乎想要同步地 运行 子进程,那么简化事情并 use subprocess.run 代替(Popen 的同步,一体式包装),所以它 captures/caches 为你输出:

import subprocess

def main():
    shell_ffprobe_frame_count = ["ffprobe", "-v", "error", "-select_streams", "v:0", "-count_packets",    "-show_entries", "stream=nb_read_packets", "-of", "csv=p=0", "test.mkv"]
    output = subprocess.run(shell_ffprobe_frame_count, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)

    print(output.stdout) # 321
    print(type(output.stdout)) # <class 'str'>

    print(int(output.stdout)) # should be 321
    print(type(int(output.stdout))) # should be 'int'

if __name__ == "__main__":
    main()

这也将适当地确保进程完成并确定性地清理为其分配的资源。

当您调用 read 时,发生了两件事:它 returns '321',它在提供输出的缓冲区中推进一个指针。再次调用 read 不会重新阅读上一件事 returned;它 return 是该指针当前位置的任何内容。

只有你第一次打电话给 read returned '321'。第二个也是returned '',表示流结束,空串还是str类型的值。第三次调用 also returns '',这不是 int.

的有效参数

如果您想再次使用 保存 return 值:

x = output.stdout.read()
print(type(x))  # <class 'str'>
print(int(x))  # 321
print(type(int(x)))  # <class 'int'>