等待外部程序完成写入文件 [英] Wait for external program to finish writing to file
问题描述
我有一个调用外部程序的 Python 脚本(准确地说是 sox
).现在我必须用 sox
做几件事,但总是要等到一个文件写完,这样我才能在下一个命令中将它用作输入文件.
I have a Python script that calls an external program (sox
to be precise). Now I have to do several things with sox
, but always have to wait until one file is done writing so I can use it as an input file in my next command.
subprocess.wait()
不起作用,因为sox
的执行会完成,但文件不会写完.
subprocess.wait()
doesn't work, because the execution of sox
will be done, but the file won't be done writing.
这是我的代码:
import tempfile
import shlex
file_url = '/some/file.wav'
out_file = 'some/out.wav'
tmp_file = tempfile.NamedTemporaryFile()
pad_cmd = 'sox ' + file_url + ' ' + tmp_file.name + ' pad 0.0 3.0'
subprocess.call(shlex.split(pad_cmd))
trim_cmd = 'sox ' + tmp_file.name + ' -t wav ' + out_file + ' trim 0.0 3.0'
等待文件完成写入 tmp_file.name
的任何方法,而不使用等待固定时间的计时器.或者 sox
中是否有使用输出文件作为输入的内置方法?特殊文件名 -
不适用于 pad
和 trim
.
Any way to wait for the file to finish writing to tmp_file.name
without using a timer that waits for a fixed amount of time. Or is there a built-in way in sox
to use the output file as input? The special filename -
didn't work for pad
and trim
.
推荐答案
If sox
适用于标准输入/标准输出:
If sox
works with stdin/stdout:
#!/bin/sh
sox input.wav -t wav - pad 0.0 3.0 | sox -t wav - out.wav trim 0.0 3.0
那么你可以用 Python 编写它:
then you could write it in Python:
#!/usr/bin/env python
from subprocess import Popen, PIPE
pad = Popen(["sox", "input.wav", "-t", "wav", "-", "pad", "0.0", "3.0"],
stdout=PIPE)
trim = Popen(['sox', '-t', 'wav', '-', 'out.wav', 'trim', '0.0', '3.0'],
stdin=pad.stdout)
pad.stdout.close() # notify pad on write if trim dies prematurely
pipestatus = [p.wait() for p in [pad, trim]]
注意:如果您不使用不受信任的输入来构造命令,那么您可以将它们作为单行传递以提高可读性(在这种情况下,shell 创建了管道):
Note: if you don't use an untrusted input to construct the commands then you could pass them as a single line for readability (the shell creates the pipe in this case):
#!/usr/bin/env python
from subprocess import check_call
cmd = "sox input.wav - -t wav pad 0.0 3.0 | sox - -t wav out.wav trim 0.0 3.0"
check_call(cmd, shell=True)
<小时>
如果你不能写/读到/从标准输出/标准输入,那么你可以尝试一个命名管道,以避免等待文件:
If you can't make it to write/read to/from stdout/stdin then you could try a named pipe, to avoid waiting for a file:
#!/bin/sh
mkfifo /tmp/sox.fifo
sox /tmp/sox.fifo -t wav out.wav trim 0.0 3.0 & # read from fifo
sox input.wav /tmp/sox.fifo pad 0.0 3.0 # write to fifo
或在 Python 中相同:
or the same in Python:
#!/usr/bin/env python
from subprocess import Popen, check_call
with named_pipe() as path:
trim = Popen(["sox", path, '-t', 'wav', 'out.wav', 'trim', '0.0', '3.0'])
check_call(["sox", "input.wav", path, "pad", "0.0", "3.0"]) # pad
rc = trim.wait()
其中 named_pipe()
定义为:
import os
from contextlib import contextmanager
from shutil import rmtree
from tempfile import mkdtemp
@contextmanager
def named_pipe():
dirname = mkdtemp()
try:
path = os.path.join(dirname, 'named_pipe')
os.mkfifo(path)
yield path
finally:
rmtree(dirname)
这篇关于等待外部程序完成写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!