代码之家  ›  专栏  ›  技术社区  ›  marjun

使用python从s3读取文件名[重复]

  •  0
  • marjun  · 技术社区  · 7 年前

    subprocess 模块?

    echo "input data" | awk -f script.awk | sort > outfile.txt
    

    输入数据将来自字符串,因此我实际上不需要 echo sort 我也是?

    p_awk = subprocess.Popen(["awk","-f","script.awk"],
                              stdin=subprocess.PIPE,
                              stdout=file("outfile.txt", "w"))
    p_awk.communicate( "input data" )
    

    :请注意,虽然下面接受的答案实际上并没有回答所问的问题,但我相信S.Lott是对的,最好不要一开始就解决这个问题!

    0 回复  |  直到 11 年前
        1
  •  46
  •   Adam Spiers    10 年前

    你会更开心的。

    import subprocess
    
    awk_sort = subprocess.Popen( "awk -f script.awk | sort > outfile.txt",
        stdin=subprocess.PIPE, shell=True )
    awk_sort.communicate( b"input data\n" )
    

    将部分工作委托给shell。让它用管道连接两个进程。

    编辑

    [有太多理由通过评论作出回应。]

    1. Awk正在添加一个没有显著价值的步骤。awk的处理没有Python无法处理的独特之处。

    2. 对于大型数据集,从awk到sort的流水线操作可能会缩短处理时间。对于短数据集,它没有显著的好处。快速测量 awk >file ; sort file awk | sort 将显示并发性有帮助。对于sort,它很少有帮助,因为sort不是一个一次性的过滤器。

    3. Awk(就像shell脚本本身)添加了另一种编程语言。如果所有这些都可以在一种语言(Python)中完成,那么消除shell和awk编程就消除了两种编程语言,允许有人专注于任务中产生价值的部分。

    边栏 为什么要建管道( a | b )太难了。

    a | b公司 它必须做到以下几点。

    1. 建立操作系统管道。(不是Python subprocess.PIPE)而是调用 os.pipe() 它返回两个通过公共缓冲区连接的新文件描述符。此时,进程有来自其父进程的stdin、stdout和stderr,外加一个文件,该文件将是“a的stdout”和“b的stdin”。

    2. 用叉子叉孩子。孩子用新的a的标准输出代替了它的标准输出。执行 a 过程。

    3. b

    4. b子项等待a完成。

    我认为上面的代码可以递归地用来生成 a | b | c ,但必须将长管道隐式括起来,将其视为 a | (b | c)

    因为Python已经 操作系统管道() os.exec() os.fork() ,您可以替换 sys.stdin sys.stdout ,有一种方法可以在纯Python中完成上述操作。实际上,您可以使用 操作系统管道() subprocess.Popen .

    但是,将该操作委托给shell更容易。

        2
  •  29
  •   jfs    11 年前
    import subprocess
    
    some_string = b'input_data'
    
    sort_out = open('outfile.txt', 'wb', 0)
    sort_in = subprocess.Popen('sort', stdin=subprocess.PIPE, stdout=sort_out).stdin
    subprocess.Popen(['awk', '-f', 'script.awk'], stdout=sort_in, 
                     stdin=subprocess.PIPE).communicate(some_string)
    
        3
  •  18
  •   jfs    11 年前

    from subprocess import check_call
    
    check_call('echo "input data" | a | b > outfile.txt', shell=True)
    

    不调用shell(请参见 17.1.4.2. Replacing shell pipeline ):

    #!/usr/bin/env python
    from subprocess import Popen, PIPE
    
    a = Popen(["a"], stdin=PIPE, stdout=PIPE)
    with a.stdin:
        with a.stdout, open("outfile.txt", "wb") as outfile:
            b = Popen(["b"], stdin=a.stdout, stdout=outfile)
        a.stdin.write(b"input data")
    statuses = [a.wait(), b.wait()] # both a.stdin/stdout are closed already
    

    plumbum

    #!/usr/bin/env python
    from plumbum.cmd import a, b # magic
    
    (a << "input data" | b > "outfile.txt")()
    

    类似于:

    #!/bin/sh
    echo "input data" | awk -f script.awk | sort > outfile.txt
    

    是:

    #!/usr/bin/env python
    from plumbum.cmd import awk, sort
    
    (awk["-f", "script.awk"] << "input data" | sort > "outfile.txt")()
    
        4
  •  4
  •   Omry Yadan    7 年前

    公认的答案是回避这个问题。 请注意,它还打印(多少)等效的shell命令,以便您可以运行它并确保输出正确。

    #!/usr/bin/env python3
    
    from subprocess import Popen, PIPE
    
    # cmd1 : dd if=/dev/zero bs=1m count=100
    # cmd2 : gzip
    # cmd3 : wc -c
    cmd1 = ['dd', 'if=/dev/zero', 'bs=1M', 'count=100']
    cmd2 = ['tee']
    cmd3 = ['wc', '-c']
    print(f"Shell style : {' '.join(cmd1)} | {' '.join(cmd2)} | {' '.join(cmd3)}")
    
    p1 = Popen(cmd1, stdout=PIPE, stderr=PIPE) # stderr=PIPE optional, dd is chatty
    p2 = Popen(cmd2, stdin=p1.stdout, stdout=PIPE)
    p3 = Popen(cmd3, stdin=p2.stdout, stdout=PIPE)
    
    print("Output from last process : " + (p3.communicate()[0]).decode())
    
    # thoretically p1 and p2 may still be running, this ensures we are collecting their return codes
    p1.wait()
    p2.wait()
    print("p1 return: ", p1.returncode)
    print("p2 return: ", p2.returncode)
    print("p3 return: ", p3.returncode)
    
        5
  •  3
  •   geocar    12 年前

    http://www.python.org/doc/2.5.2/lib/node535.html 很好的掩盖了这件事。你是不是有些地方不明白?

    Popen 将stdout=设置为一个文件,而不需要它的输出 .communicate() .

        6
  •  2
  •   I159    11 年前

    grep_proc = subprocess.Popen(["grep", "rabbitmq"],
                                 stdin=subprocess.PIPE, 
                                 stdout=subprocess.PIPE)
    subprocess.Popen(["ps", "aux"], stdout=grep_proc.stdin)
    out, err = grep_proc.communicate()
    

    已经做了什么

    • 宣布懒惰 grep ps 当管道将填充 聚苯乙烯
    • 聚苯乙烯 标准输出指向 格雷普
    • Grep通过通信从管道获取stdout。

    subprocess

        7
  •  1
  •   Kyle Strand    11 年前

    pipes 在Windows上是可用的,但最重要的是,看起来并不是 工作 在窗户上。见下面的评论。

    处理此问题的模块:

    https://docs.python.org/2/library/pipes.html , https://docs.python.org/3.4/library/pipes.html

    subprocess .

        8
  •  1
  •   uncleremus    8 年前

    Replacing shell pipeline 基本上是正确的,正如geocar所指出的。它是 几乎 足以运行 communicate 在管道的最后一个元素上。

    输入数据 输送管道。对于多个子流程,一个简单的 communicate(input_data) 最后一个元素不起作用-它永远挂着。您需要手动创建管道和子管道,如下所示:

    import os
    import subprocess
    
    input = """\
    input data
    more input
    """ * 10
    
    rd, wr = os.pipe()
    if os.fork() != 0: # parent
        os.close(wr)
    else:              # child
        os.close(rd)
        os.write(wr, input)
        os.close(wr)
        exit()
    
    p_awk = subprocess.Popen(["awk", "{ print $2; }"],
                             stdin=rd,
                             stdout=subprocess.PIPE)
    p_sort = subprocess.Popen(["sort"], 
                              stdin=p_awk.stdout,
                              stdout=subprocess.PIPE)
    p_awk.stdout.close()
    out, err = p_sort.communicate()
    print (out.rstrip())
    

    现在,子项通过管道提供输入,父项调用communicate(),其工作方式与预期一致。使用这种方法,您可以创建任意长的管道,而无需求助于“将部分工作委托给shell”。不幸的是 subprocess documentation

    有几种方法可以在不使用管道的情况下达到相同的效果:

    from tempfile import TemporaryFile
    tf = TemporaryFile()
    tf.write(input)
    tf.seek(0, 0)
    

    stdin=tf 对于 p_awk . 你喜欢什么取决于口味。

    由于信号处理方式不同,上述方法仍然不能完全等同于bash管道。如果添加另一个管道元素来截断 sort ,例如。 head -n 10 . 上面的代码, 会将“断管”错误消息打印到 stderr . 在shell中运行相同的管道时,不会看到此消息。(这是唯一的区别,结果是 stdout Popen SIG_IGN 对于 SIGPIPE SIG_DFL ,和 这两种情况下的信号处理不同。

        9
  •  0
  •   mwag    7 年前

    对我来说,下面的方法是最简洁易懂的

    from subprocess import Popen, PIPE
    
    def string_to_2_procs_to_file(input_s, first_cmd, second_cmd, output_filename):
        with open(output_filename, 'wb') as out_f:
            p2 = Popen(second_cmd, stdin=PIPE, stdout=out_f)
            p1 = Popen(first_cmd, stdout=p2.stdin, stdin=PIPE)
            p1.communicate(input=bytes(input_s))
            p1.wait()
            p2.stdin.close()
            p2.wait()
    

    可以这么说:

    string_to_2_procs_to_file('input data', ['awk', '-f', 'script.awk'], ['sort'], 'output.txt')