如何将stdin视为文本文件

时间:2015-05-15 04:50:20

标签: python python-3.x command-line

我有一个程序,它读取解析文本文件并对其进行一些分析。我想修改它,以便它可以通过命令行获取参数。当它被指定为stdin时从文件中读取。

解析器如下所示:

ViewControllerA

它解析看起来像这样的文件:

class FastAreader :
    '''
    Class to provide reading of a file containing one or more FASTA
    formatted sequences:
    object instantiation:
    FastAreader(<file name>):

    object attributes:
    fname: the initial file name

    methods:
    readFasta() : returns header and sequence as strings.
    Author: David Bernick
    Date: April 19, 2013
    '''
    def __init__ (self, fname):
        '''contructor: saves attribute fname '''
        self.fname = fname

    def readFasta (self):
        '''
        using filename given in init, returns each included FastA record
        as 2 strings - header and sequence.
        whitespace is removed, no adjustment is made to sequence contents.
        The initial '>' is removed from the header.
        '''
        header = ''
        sequence = ''

        with open(self.fname) as fileH:
            # initialize return containers
            header = ''
            sequence = ''

            # skip to first fasta header
            line = fileH.readline()
            while not line.startswith('>') :
                line = fileH.readline()
            header = line[1:].rstrip()

            # header is saved, get the rest of the sequence
            # up until the next header is found
            # then yield the results and wait for the next call.
            # next call will resume at the yield point
            # which is where we have the next header
            for line in fileH:
                if line.startswith ('>'):
                    yield header,sequence
                    header = line[1:].rstrip()
                    sequence = ''
                else :
                    sequence += ''.join(line.rstrip().split()).upper()
        # final header and sequence will be seen with an end of file
        # with clause will terminate, so we do the final yield of the data
        yield header,sequence

# presumed object instantiation and example usage
# myReader = FastAreader ('testTiny.fa');
# for head, seq in myReader.readFasta() :
#     print (head,seq)

我的测试程序如下所示:

>test
ATGAAATAG
>test2
AATGATGTAA
>test3
AAATGATGTAA

>test-1
TTA CAT CAT

>test-2
TTA CAT CAT A

>test-3
TTA CAT CAT AA

>test1A
ATGATGTAAA
>test2A
AATGATGTAAA
>test3A
AAATGATGTAAA

>test-1A
A TTA CAT CAT

>test-2A
AA TTA CAT CAT A

>test-3A
AA TTA CAT CAT AA

我的命令行输入如下所示:

import argparse
import sequenceAnalysis as s
import sys

class Test:
    def __init__(self, infile, longest, min, start):
        self.longest = longest
        self.start = set(start)
        self.infile = infile
        self.data = sys.stdin.read()
        self.fasta = s.FastAreader(self.data)
        for head, seq in self.fasta.readFasta():
            self.head = head
            self.seq = "".join(seq).strip()
        self.test()

    def test(self):
        print("YUP", self.start, self.head)


def main():
    parser = argparse.ArgumentParser(description = 'Program prolog', 
                                     epilog = 'Program epilog', 
                                     add_help = True, #default is True 
                                     prefix_chars = '-', 
                                     usage = '%(prog)s [options] -option1[default] <input >output')
    parser.add_argument('-i', '--inFile', action = 'store', help='input file name')
    parser.add_argument('-o', '--outFile', action = 'store', help='output file name') 
    parser.add_argument('-lG', '--longestGene', action = 'store', nargs='?', const=True, default=True, help='longest Gene in an ORF')
    parser.add_argument('-mG', '--minGene', type=int, choices= range(0, 2000), action = 'store', help='minimum Gene length')
    parser.add_argument('-s', '--start', action = 'append', nargs='?', help='start Codon') #allows multiple list options
    parser.add_argument('-v', '--version', action='version', version='%(prog)s 0.1')  
    args = parser.parse_args()
    test = Test(args.inFile, args.longestGene, args.minGene, args.start)


if __name__ == '__main__':
    main()

其中tass2.fa是一个可由FastAreader解析的文件。我可以传递像start这样的参数并让它们输出到文本文件但是当我尝试解析应该是stdin的输入文件时它打印所有内容而不是解析它而不是输出到应该是stdout的指定文本文件它打印它直接到命令行。

1 个答案:

答案 0 :(得分:2)

当您使用I / O重定向时(即命令行中有<|><<),即使是shell也会处理在程序运行之前。因此,当Python运行时,其标准输入连接到您要重定向的文件或管道,并且其标准输出连接到您重定向到的文件或管道,并且文件名不会(直接)对Python可见,因为您正在处理已经open()的ed文件句柄,而不是文件名。您的参数解析器根本不返回任何内容,因为没有文件名参数。

要正确处理此问题,您应该调整代码以直接使用文件句柄 - 而不是显式文件名,或者除了显式文件名之外。

对于后一种情况,一个常见的约定是文件名-有一个特殊情况,当传入时,使用标准输入(或标准输出,取决于上下文)而不是打开文件。 (通过使用相对路径./-的简单解决方法,您仍然可以使用这样命名的文件,因此名称不是一个短划线。)