Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python子进程将stdout重定向到stdin?_Python_Shell_Unix_Streaming_Subprocess - Fatal编程技术网

使用Python子进程将stdout重定向到stdin?

使用Python子进程将stdout重定向到stdin?,python,shell,unix,streaming,subprocess,Python,Shell,Unix,Streaming,Subprocess,我正在使用子进程模块从shell调用一个程序,该模块将二进制文件输出到STDOUT 我使用Popen调用该程序,然后我想将流传递给一个名为pysam的Python包中的函数,不幸的是,该函数不能读取Python文件对象,但可以从STDIN读取。所以我想做的是让shell命令的输出从STDOUT转到STDIN 如何在Popen/子流程模块中实现这一点?这是我调用shell程序的方式: p = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, shel

我正在使用子进程模块从shell调用一个程序,该模块将二进制文件输出到STDOUT

我使用Popen调用该程序,然后我想将流传递给一个名为pysam的Python包中的函数,不幸的是,该函数不能读取Python文件对象,但可以从STDIN读取。所以我想做的是让shell命令的输出从STDOUT转到STDIN

如何在Popen/子流程模块中实现这一点?这是我调用shell程序的方式:

p = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, shell=True).stdout
这将读取my_cmd的STDOUT输出,并在p中获得一个流。由于我的Python模块无法直接从p读取,因此我尝试使用以下命令将我的_cmd的STDOUT重定向回STDIN:

p = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True).stdout
然后我调用我的模块,该模块使用-作为STDIN的占位符:

s = pysam.Samfile("-", "rb")
上面的调用只意味着从STDIN读取,并将其作为二进制文件rb读取

当我尝试这一点时,我只是将二进制输出发送到屏幕上,而Samfile函数似乎无法读取它。即使我删除了对Samfile的调用,也会发生这种情况,因此我认为问题出在我对Popen的调用上,而不是下游步骤

编辑:在回答问题时,我尝试:

sys.stdin = subprocess.Popen(tagBam_cmd, stdout=subprocess.PIPE, shell=True).stdout
print "Opening SAM.."                                                                                            
s = pysam.Samfile("-","rb")
print "Done?"
sys.stdin = sys.__stdin__    
这似乎很难解决。我得到输出:

Opening SAM..
但它永远不会超过Samfile-,rb行。知道为什么吗

你知道怎么解决这个问题吗

编辑2:我正在添加一个Pysam文档的链接,以防它有所帮助,我真的无法理解这一点。文档页面为:

关于streams的具体说明如下:

特别是:

Pysam不支持从真正的python文件对象读写,但它支持从stdin和stdout读写。以下示例从stdin读取并写入stdout:

infile = pysam.Samfile( "-", "r" )
outfile = pysam.Samfile( "-", "w", template = infile )
for s in infile: outfile.write(s)
它还可以处理BAM文件。以下脚本将stdin上的BAM格式文件转换为stdout上的SAM格式文件:

infile = pysam.Samfile( "-", "rb" )
outfile = pysam.Samfile( "-", "w", template = infile )
for s in infile: outfile.write(s)
注意,只有文件打开模式需要从r更改为rb。

所以我只想获取来自Popen的流,它读取stdout,并将其重定向到stdin,这样我就可以使用Samfile-,rb,因为上面的部分状态是可能的


谢谢。

如果您使用的是stdout=subprocess.PIPE,您会在stdout上看到二进制文件,这让我有点困惑。但是,总体问题是,如果您想欺骗pysam使用它,您需要使用sys.stdin

例如:

sys.stdin = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, shell=True).stdout
s = pysam.Samfile("-", "rb")
sys.stdin = sys.__stdin__ # restore original stdin
更新:假设pysam是在Python解释器的上下文中运行的,因此在指定时表示Python解释器的stdin。不幸的是,事实并非如此;当指定-时,它直接从文件描述符0读取

换句话说,它没有使用Python的stdinsys.stdin概念,因此替换它对pysam.Samfile没有影响。也不可能从Popen调用获取输出并以某种方式将其推送到文件描述符0;它是只读的,另一端连接到终端

将该输出放到文件描述符0上的唯一实际方法是将其移动到另一个脚本,并从第一个脚本开始将这两个脚本连接在一起。这确保了第一个脚本中Popen的输出将在第二个脚本的文件描述符0上结束


因此,在本例中,最好的选择是将其拆分为两个脚本。第一个将调用my_cmd并获取该命令的输出,并将其用作另一个Python脚本的第二个Popen的输入,该脚本调用pysam.Samfile-,rb。

如果使用stdout=subprocess.PIPE,您会在stdout上看到二进制文件,但我有点困惑,总的问题是,如果要诱使pysam使用sys.stdin,就需要使用它

例如:

sys.stdin = subprocess.Popen(my_cmd, stdout=subprocess.PIPE, shell=True).stdout
s = pysam.Samfile("-", "rb")
sys.stdin = sys.__stdin__ # restore original stdin
更新:假设pysam是在Python解释器的上下文中运行的,因此在指定时表示Python解释器的stdin。不幸的是,事实并非如此;当指定-时,它直接从文件描述符0读取

换句话说,它没有使用Python的stdinsys.stdin概念,因此替换它对pysam.Samfile没有影响。也不可能从Popen调用获取输出并以某种方式将其推送到文件描述符0;它是只读的,另一端连接到终端

将该输出放到文件描述符0上的唯一实际方法是将其移动到另一个脚本,并从第一个脚本开始将这两个脚本连接在一起。这确保了第一个脚本中Popen的输出将在第二个脚本的文件描述符0上结束


因此,在本例中,最好的选择是将其拆分为两个脚本。第一个将调用my_cmd并获取该命令的输出,并将其用作另一个Python脚本的第二个Popen的输入,该脚本调用pysam.Samfile-,rb。

在处理pysam的特定情况下,我能够使用命名管道解决该问题http://docs.python.org/library/os.htmlos.mkfifo,这是一个可以像普通文件一样访问的管道。总的来说,哟 您希望管道的用户读者在您开始向管道写入内容之前倾听,以确保您不会遗漏任何内容。但是,如果stdin上没有注册任何内容,pysam.Samfile-,rb将挂起,如上所述

假设您正在处理需要相当长时间的先前计算,例如,在将bam传递到pysam之前对bam进行排序,您可以启动该先前计算,然后在任何内容得到输出之前监听流:

import os
import tempfile
import subprocess
import shutil
import pysam

# Create a named pipe
tmpdir = tempfile.mkdtemp()
samtools_prefix = os.path.join(tmpdir, "namedpipe")
fifo = samtools_prefix + ".bam"
os.mkfifo(fifo)

# The example below sorts the file 'input.bam',
# creates a pysam.Samfile object of the sorted data,
# and prints out the name of each record in sorted order

# Your prior process that spits out data to stdout/a file
# We pass samtools_prefix as the output prefix, knowing that its
# ending file will be named what we called the named pipe
subprocess.Popen(["samtools", "sort", "input.bam", samtools_prefix])

# Read from the named pipe
samfile = pysam.Samfile(fifo, "rb")

# Print out the names of each record
for read in samfile:
    print read.qname

# Clean up the named pipe and associated temp directory
shutil.rmtree(tmpdir)

在处理pysam的具体案例中,我能够使用命名管道解决这个问题http://docs.python.org/library/os.htmlos.mkfifo,这是一个可以像普通文件一样访问的管道。一般来说,您希望管道的消费者读者在开始向管道写入内容之前倾听,以确保不会遗漏任何内容。但是,如果stdin上没有注册任何内容,pysam.Samfile-,rb将挂起,如上所述

假设您正在处理需要相当长时间的先前计算,例如,在将bam传递到pysam之前对bam进行排序,您可以启动该先前计算,然后在任何内容得到输出之前监听流:

import os
import tempfile
import subprocess
import shutil
import pysam

# Create a named pipe
tmpdir = tempfile.mkdtemp()
samtools_prefix = os.path.join(tmpdir, "namedpipe")
fifo = samtools_prefix + ".bam"
os.mkfifo(fifo)

# The example below sorts the file 'input.bam',
# creates a pysam.Samfile object of the sorted data,
# and prints out the name of each record in sorted order

# Your prior process that spits out data to stdout/a file
# We pass samtools_prefix as the output prefix, knowing that its
# ending file will be named what we called the named pipe
subprocess.Popen(["samtools", "sort", "input.bam", samtools_prefix])

# Read from the named pipe
samfile = pysam.Samfile(fifo, "rb")

# Print out the names of each record
for read in samfile:
    print read.qname

# Clean up the named pipe and associated temp directory
shutil.rmtree(tmpdir)

如果您的系统支持它;你可以:


如果您的系统支持它;你可以:



导入sys,sys.stdin.writep.stdout.read?在写入stdin之前,请确保s=pysam.Samfile-,rb。您仍然看到屏幕上的二进制输出吗?换句话说,你确定你的tagBam_cmd真的在将结果发送到stdout吗?我没有看到二进制屏幕,我只是看到程序挂起。当我运行tagBam_cmd的内容时,它会将其打印到屏幕上,因此我假设它是标准输出。如何检查呢?在shell中以:tagBam\u cmd>test\u输出的形式运行tagBam\u cmd,看看二进制文件是否在文件中结束。如果没有,那么它可能会转到stderr。我已经这样做了,它肯定会转到文件。import sys,sys.stdin.writep.stdout.read?在写入stdin之前,请确保s=pysam.Samfile-,rb。您仍然看到屏幕上的二进制输出吗?换句话说,你确定你的tagBam_cmd真的在将结果发送到stdout吗?我没有看到二进制屏幕,我只是看到程序挂起。当我运行tagBam_cmd的内容时,它会将其打印到屏幕上,因此我假设它是标准输出。如何检查呢?在shell中以:tagBam\u cmd>test\u输出的形式运行tagBam\u cmd,看看二进制文件是否在文件中结束。如果没有,那么它可能会转到stderr。我已经这样做了,它肯定会转到文件。虽然我更喜欢只写sys.stdin,而不是在主帖子上看到我的评论。这是行不通的。您将尝试写入只读的文件流对象,而不是为将来的读取推送数据。现在,如果你打开/dev/fd/0并写信给它,如果可以的话。@DavidK.Hess:我试过你的建议,但它似乎挂在Samfile上。。。对你有用吗?请参阅“编辑到我的原始帖子”。@user248237查看我的编辑-您确定pyasm正在从解释器的stdin读取数据,还是正在运行带有这些参数的外部程序?指向pyasm.Samfile文档的链接也会有所帮助。@DavidK.Hess:添加链接。相关部分在这里:虽然我更喜欢只写信给sys.stdin,而不是在主要帖子上看到我的评论。这是行不通的。您将尝试写入只读的文件流对象,而不是为将来的读取推送数据。现在,如果你打开/dev/fd/0并写信给它,如果可以的话。@DavidK.Hess:我试过你的建议,但它似乎挂在Samfile上。。。对你有用吗?请参阅“编辑到我的原始帖子”。@user248237查看我的编辑-您确定pyasm正在从解释器的stdin读取数据,还是正在运行带有这些参数的外部程序?指向pyasm.Samfile文档的链接也会有所帮助。@DavidK.Hess:添加链接。相关部分在这里:如果系统支持它,那么它可能更容易实现。如果系统支持它,那么它可能更容易实现。