如何直接在控制台上对文件进行子处理(使用或不使用 StringIO)?

How to subprocess the files on console directly (with or without using StringIO)?

我正在尝试读取一个 gtf 文件,然后在加载到 pandas 之前对其进行编辑(使用子进程、grep 和 awk)。

我有一个包含 header 信息的文件名(由 # 表示),所以我需要先 grep 并删除它。我可以在 python 中完成,但我想将 grep 引入我的管道以提高处理效率。

我试过:

import subprocess
from io import StringIO

gtf_file = open('chr2_only.gtf', 'r').read()
gtf_update = subprocess.Popen(["grep '^#' " + StringIO(gtf_file)], shell=True)

gtf_update = subprocess.Popen(["grep '^#' " + gtf_file], shell=True)

这两个代码都抛出错误,第一次尝试是:

Traceback (most recent call last):
  File "/home/everestial007/PycharmProjects/stitcher/pHASE-Stitcher-Markov/markov_final_test/phase_to_vcf.py", line 39, in <module> gtf_update = subprocess.Popen(["grep '^#' " + StringIO(gtf_file)], shell=True)
TypeError: Can't convert '_io.StringIO' object to str implicitly

但是,如果我直接指定文件名,它会起作用:

gtf_update = subprocess.Popen(["grep '^#' chr2_only.gtf"], shell=True)

输出为:

<subprocess.Popen object at 0x7fc12e5ea588>
#!genome-build v.1.0
#!genome-version JGI8X
#!genome-date 2008-12
#!genome-build-accession GCA_000004255.1
#!genebuild-last-updated 2008-12

有人可以为这样的问题提供不同的示例,并解释为什么我会收到错误并且 why/how 可以 运行 直接对文件进行子处理加载于 console/memory?

我也尝试过将 subprocesscall, check_call, check_output, etc. 一起使用,但我收到了几个不同的错误消息,例如:

OSError: [Errno 7] Argument list too long

Subprocess in Python: File Name too long

这是一个可能的解决方案,允许您将字符串发送到 grep。本质上,您在 Popen 构造函数中声明您希望通过标准输入和标准输出与被调用程序通信。然后,您通过通信发送输入并从通信接收输出作为 return 值。

#!/usr/bin/python

import subprocess

gtf_file = open('chr2_only.gtf', 'r').read()
gtf_update = subprocess.Popen(["grep '^#' "], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# stdout, stderr (but latter is empty)
gtf_filtered, _ = gtf_update.communicate(gtf_file)

print gtf_filtered

请注意,最好不要使用 shell=True。因此,Popen行应该写成

gtf_update = subprocess.Popen(["grep", '^#'], shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

理由是您不需要 shell 将参数解析为单个可执行文件。因此,您可以避免不必要的开销。从安全的角度来看,它也更好,至少当某些参数来自用户时可能不安全(想想包含 | 的文件名)。 (这里显然不是这种情况。)

请注意,从性能的角度来看,我希望直接使用 grep 读取文件比先使用 python 读取文件然后将其发送到 grep 更快。