等待外部程序完成写入文件 [英] Wait for external program to finish writing to file

查看:40
本文介绍了等待外部程序完成写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个调用外部程序的 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 中是否有使用输出文件作为输入的内置方法?特殊文件名 - 不适用于 padtrim.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆