更多 < 子进程调用中的运算符 Python

more < operator in subprocess call Python

我有三个csv文件:1.csv, 2.csv, 3.csv 像这样:

➜  ~  cat 1.csv 
1,1,1,1,1,1
➜  ~  cat 2.csv 
2,2,2,2,2,2
➜  ~  cat 3.csv 
3,3,3,3,3,3

如果我这样做:

➜  ~  cat < 1.csv < 2.csv < 3.csv > 4.csv

我获得:

➜  ~  cat 4.csv 
1,1,1,1,1,1
2,2,2,2,2,2
3,3,3,3,3,3

如我所愿

现在我想在 Python subprocess.call

中执行此操作
import subprocess as sp

sp.call('cat < 1.csv < 2.csv < 3.csv > 4.csv', shell=True)

但结果是:

➜  ~  cat 4.csv 
3,3,3,3,3,3

在这些方式中它不会创建 4.csv 文件:

sp.call(['cat', '<', '1.csv', '<', '2.csv', '<', '3.csv', '>', '4.csv'], stdout=sp.PIPE,stderr=sp.PIPE

mylist = ['cat', '<', '1.csv', '<', '2.csv', '<', '3.csv', '>', '4.csv']
sp.call(mylist, stdout=sp.PIPE,stderr=sp.PIPE)

只需使用 python:

即可轻松实现
import fileinput
with open("4.csv", "a") as out:
    for f in fileinput.input(["1.csv","2.csv","3.csv"]):
        out.write(f)

使用子进程你可以重定向:

from subprocess import check_call
with open("4.csv", "a") as out:
     check_call(["cat", "1.csv", "2.csv", "3.csv"],stdout=out)

我建议使用第一个示例。

这两个都有效:

sp.call('cat 1.csv 2.csv 3.csv > 4.csv', shell=True)

sp.call('cat < 1.csv > 4.csv', shell=True) sp.call('cat < 2.csv >> 4.csv', shell=True) sp.call('cat < 3.csv >> 4.csv', shell=True)

不确定您真正的 objective 是什么。如果您只想连接一些文件,那么直接在 python 中进行连接是可行的方法。如果你想链式附加一些程序输出,那么我会使用第二种方法(每行一个)。

如果多次重定向,则执行所有重定向,但只有最后一次重定向生效(假设none之前的重定向导致错误)。

$ cat < 1.csv < 2.csv < 3.csv > 4.csv

以上等同于:

$ cat < 3.csv > 4.csv

除非 1.csv、2.csv 或 3.csv 中的任何一个都不存在,在这种情况下此命令将失败。

试试这个:

import subprocess as sp
sp.call('cat  1.csv  2.csv  3.csv > 4.csv', shell=True)

如果太慢,您可以尝试使用更大的块进行复制:

#!/usr/bin/env python
from shutil import copyfileobj

with open('4.csv', 'wb') as output_file:
    for filename in ['1.csv', '2.csv', '3.csv']:
        with open(filename, 'rb') as file:
            copyfileobj(file, output_file)

copyfileobj() 接受 length 参数,您可以试验该参数以了解它如何影响您的情况下的时间性能。

如果还不够,可以试试os.sendfile():

#!/usr/bin/env python3
import os

with open('4.csv', 'wb') as output_file:
    for filename in ['1.csv', '2.csv', '3.csv']:
        with open(filename, 'rb') as file:
            while os.sendfile(output_file.fileno(), file.fileno(), None, 1 << 30) != 0:
                pass