繁体   English   中英

需要使用子进程模块在 2 个 NamedTemporaryFiles 上运行 diff 命令

[英]Need to run a diff command on 2 NamedTemporaryFiles using subprocess module

我试图在 2 个命名的临时文件上运行差异,我没有使用 difflib,因为它的输出与 linux 差异不同。 当我运行此代码时,它不输出任何内容。 我尝试了对常规文件的差异,效果很好。

#using python 2.6
temp_stage = tempfile.NamedTemporaryFile(delete = False)
temp_prod = tempfile.NamedTemporaryFile(delete = False)
temp_stage.write(stage_notes)
temp_prod.write(prod_notes)

#this does not work, shows no output, tried both call and popen
subprocess.Popen(["diff", temp_stage.name, temp_prod.name])

#subprocess.call(["diff", temp_stage.name, temp_prod.name])

您需要通过调用flush()强制将文件写入磁盘; 否则您写入文件的数据可能只存在于缓冲区中。

事实上,如果你这样做,你甚至可以使用delete = True ,假设没有其他理由保留文件。 这保留了使用临时文件的好处。

#!/usr/bin/python2
temp_stage = tempfile.NamedTemporaryFile(delete = True)
temp_prod = tempfile.NamedTemporaryFile(delete = True)
temp_stage.write(stage_notes)
temp_prod.write(prod_notes)

temp_stage.flush()
temp_prod.flush()

subprocess.Popen(["diff", temp_stage.name, temp_prod.name])

与您的.flush()问题无关,您可以通过 stdin 传递一个文件,而不是将数据写入磁盘:

from tempfile import NamedTemporaryFile
from subprocess import Popen, PIPE

with NamedTemporaryFile() as file:
    file.write(prod_notes)
    file.flush()
    p = Popen(['diff', '-', file.name], stdin=PIPE)
    p.communicate(stage_notes) # diff reads the first file from stdin

if p.returncode == 0:
    print('the same')
elif p.returncode == 1:
    print('different')
else:
    print('error %s' % p.returncode)

如果输入文件名是-diff从标准输入读取。

如果使用命名管道,则根本不需要将数据写入磁盘:

from subprocess import Popen, PIPE
from threading import Thread

with named_pipe() as path:
    p = Popen(['diff', '-', path], stdin=PIPE)
    # use thread, to support content larger than the pipe buffer
    Thread(target=p.communicate, args=[stage_notes]).start()
    with open(path, 'wb') as pipe:
        pipe.write(prod_notes)

if p.wait() == 0:
    print('the same')
elif p.returncode == 1:
    print('different')
else:
    print('error %s' % p.returncode)

其中named_pipe()上下文管理器定义为:

import os
import tempfile
from contextlib import contextmanager
from shutil import rmtree

@contextmanager
def named_pipe(name='named_pipe'):
    dirname = tempfile.mkdtemp()
    try:
        path = os.path.join(dirname, name)
        os.mkfifo(path)
        yield path
    finally:
        rmtree(dirname)

命名管道的内容不接触磁盘。

我建议绕过临时文件处理,因为使用 NTF 无论如何你都必须处理清理。 创建一个新文件并写入您的数据,然后关闭它。 刷新缓冲区,然后调用子进程命令。 看看这是否让它运行。

f=open('file1.blah','w')
f2=open('file2.blah','w')
f.write(stage_notes)
f.flush()
f.close()
f2.write(prod_notes)
f2.flush()
f2.close()

然后运行您的子流程调用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM