2015-05-15 3 views
0

У меня есть программа, которая читает анализирует текстовый файл и делает некоторый анализ на нем. Я хочу изменить его, чтобы он мог принимать параметры через командную строку. Чтение из файла, когда оно обозначено как stdin.Как обрабатывать stdin как текстовый файл

Анализатор выглядит следующим образом:

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() 

Мои входные командной строки выглядит например:

python testcommand2.py -s ATG <tass2.fa >out.txt 

Где tass2.fa - файл, который может обрабатываться FastAreader. Я могу передавать параметры, такие как start, и получать их для вывода в текстовый файл, но когда я пытаюсь разобрать входной файл, который должен быть stdin, он печатает все, а не анализирует его, а вместо вывода в указанный текстовый файл, который должен быть stdout, он печатает его непосредственно к командной строке.

+0

Это ваша командная строка примерно так: 'python test.py < in.txt > parsed.txt' ? Можете ли вы показать используемую вами командную строку (за [запрос])? – boardrider

+0

@boardrider Извините, мое сообщение отредактировано соответствующим образом. Но да, это то, что выглядит мой ввод команд. – Sam

ответ

2

При использовании перенаправления ввода/вывода (то есть вы < или | или > или << в командной строке), которая обрабатывается интерпретатором даже перед запуском вашей программы. Поэтому, когда Python запускается, его стандартный ввод связан с файлом или каналом, с которого вы перенаправляетесь, и его стандартный вывод связан с файлом или каналом, к которому вы перенаправляетесь, и имена файлов не отображаются (напрямую) на Python, потому что вы имеют дело с уже open() ed файлами, а не именами файлов. Ваш парсер аргументов просто ничего не возвращает, потому что аргументов имени файла нет.

Чтобы правильно справиться с этим, вы должны адаптировать свой код для работы с файловыми дескрипторами напрямую - вместо или в явном имени файла.

Для последнего сценария общее соглашение состоит в том, чтобы иметь специальный регистр для имени файла -, и когда он передается, вместо открытия файла используйте стандартный ввод (или стандартный вывод, в зависимости от контекста). (У вас все еще есть файлы, названные так по простейшему обходному пути использования относительного пути ./-, так что имя не является точно одним тире.)

Смежные вопросы