2016-01-13 4 views
-2

Я сейчас пишу скрипт в python, который принимает несколько флагов. Это моя первая попытка такой программы, и я получаю вывод из сценария bash, который я не совсем понимаю. Например, когда я бегу сценарий в Баш оболочки:странный вывод при использовании флагов в python

$ python my_script.py -f <input_file.txt> -k <test_string> -c <user_input> 

я получаю этот выход перед выходом моего сценария:

usage: rm [-f | -i] [-dPRrvW] file ... 
     unlink file 

Я не могу избавиться от этого, который расстраивает привлекательность выпуска. Любая помощь будет замечательной!

кода я использую:

import sys, getopt, re, subprocess, collections, itertools 

def find_kmers(arguments=sys.argv[1:]): 

    required_opts = ['-f','-c','-k'] 



    opts, args = getopt.getopt(arguments,'f:k:c:') 



    opt_dic = dict(opts) 



    for opt in required_opts: 

     if opt not in opt_dic: 

      return "incorrect arguments, please format as: python_script.py -f <filename> -k <kmer> -c <chromosome_name>" 



    def rev_comp(sequence): 

     reversed_dic = {'A':'T','T':'A','C':'G','G':'C'} 

     return ''.join(reversed_dic[_] for _ in sequence[::-1]) 



    kmer = opt_dic['-k'] 

    subprocess.call(['bash','-c',"grep '>' S288C_R64.fasta > grep.tmp"]) 

    chromosomes = [_[1:].strip() for _ in open('grep.tmp')] 

    subprocess.call(['bash','-c','rm','grep.tmp']) 

    found = False 

    if any(opt_dic['-c']==_ for _ in chromosomes): 

     found = True 



    def get_sequence(file): 

     sequence = '' 

     for line in file: 

      if line.startswith('>'): break 

      sequence += line.strip() 

     return sequence.upper() 



    ofile = open(opt_dic['-f']) 

    if found == True: 

     for line in ofile: 

      if line.startswith('>'): 

       if line[1:].strip() == opt_dic['-c']: 

        sequence = get_sequence(ofile) 

        break 



    else: 

     return 'chromosome not found in %s. \n chromosomes in file are:%s'%(opt_dic['-f'],', '.join(str(_) for _ in chromosomes)) 





    kmer_matches1 = re.finditer('(?=%s)'%opt_dic['-k'],sequence) 

    kmer_matches2 = re.finditer('(?=%s)'%opt_dic['-k'],rev_comp(sequence)) 







    def print_statement(start,strand): 



     return '%s\thw1_script\tkmer=%s\t%s\t%s\t.\t%s\t.\tID=S288C;Name=S288C\n'%(opt_dic['-c'],opt_dic['-k'],start,start+len(opt_dic['-k'])-1,strand) 



    pos_strand = collections.deque() 

    neg_strand = collections.deque() 

    for match1,match2 in itertools.izip(kmer_matches1,kmer_matches2): 

     pos_strand.append(match1.start()+1) 

     neg_strand.append(match2.start()+1) 



    wfile = open('answer.gff3','w') 

    while len(pos_strand)>0 and len(neg_strand)>0: 

     if pos_strand[0]<neg_strand[0]: 

      start = pos_strand.popleft() 

      wfile.write(print_statement(start,'+')) 

     else: 

      start = neg_strand.popleft() 

      wfile.write(print_statement(start,'-')) 



    while len(pos_strand)>0: 

     start = pos_strand.popleft() 

     wfile.write(print_statement(start,'+')) 



    while len(neg_strand)>0: 

     start = neg_strand.popleft() 

     wfile.write(print_statement(start,'-')) 



    wfile.close() 



    return 'percent-GC = %s'%str(sum(sequence.count(gc) for gc in ["G","C"])/float(len(sequence))) 



if __name__ == '__main__': 

    print find_kmers() 
+3

Проявите исходный код! – Krumelur

+4

вы явно называете «rm» откуда-то из вашего исходного кода ... вы не должны этого делать ... –

+0

О, я понял. Если я сделаю изменение командой rm для: subprocess.call (['bash', '- c', 'rm grep.tmp']), я получаю то, что хочу. Извините за немой вопрос: все – lstbl

ответ

3

bash Вызова острот требует, чтобы команды Баша быть одной строкой. Изменение:

subprocess.call(['bash','-c','rm','grep.tmp']) 

к:

subprocess.call(['bash', '-c', 'rm grep.tmp']) 

Или, более разумно, не использовать подпроцессы для этого, просто сделать:

os.unlink('grep.tmp') # Or os.remove; same thing, different names 

который гораздо быстрее и меньше ошибок.

На самом деле, все ваше использование подпроцесса может быть заменен на реальный коде Python, и это улучшило бы его существенно (и большая часть кода Python упрощает тоже):

def find_kmers(arguments=sys.argv[1:]): 
    required_opts = ['-f','-c','-k'] 

    opts, args = getopt.getopt(arguments,'f:k:c:') 

    opt_dic = dict(opts) 

    for opt in required_opts: 
     if opt not in opt_dic: 
      return "incorrect arguments, please format as: python_script.py -f <filename> -k <kmer> -c <chromosome_name>" 

    def rev_comp(sequence): 
     reversed_dic = {'A':'T','T':'A','C':'G','G':'C'} 
     return ''.join(reversed_dic[_] for _ in sequence[::-1]) 

    kmer = opt_dic['-k'] 
    # Replaces grep with temp file with trivial Python equivalent 
    with open('S288C_R64.fasta') as f: 
     chromosomes = [line[1:].strip() for line in f if '>' in line] 

    # No need for any loop when just checking for exact value 
    if opt_dic['-c'] not in chromosomes: 
     return 'chromosome not found in %s. \n chromosomes in file are:%s'%(opt_dic['-f'],', '.join(str(_) for _ in chromosomes)) 


    def get_sequence(file): 
     sequence = '' 
     for line in file: 
      if line.startswith('>'): break 
      sequence += line.strip() 
     return sequence.upper() 

    with open(opt_dic['-f']) as ofile: 
     for line in ofile: 
      if line.startswith('>'): 
       if line[1:].strip() == opt_dic['-c']: 
        sequence = get_sequence(ofile) 
        break 


    kmer_matches1 = re.finditer('(?=%s)'%opt_dic['-k'],sequence) 
    kmer_matches2 = re.finditer('(?=%s)'%opt_dic['-k'],rev_comp(sequence)) 

    def print_statement(start,strand): 
     return '%s\thw1_script\tkmer=%s\t%s\t%s\t.\t%s\t.\tID=S288C;Name=S288C\n'%(opt_dic['-c'],opt_dic['-k'],start,start+len(opt_dic['-k'])-1,strand) 

    pos_strand = collections.deque() 
    neg_strand = collections.deque() 
    for match1,match2 in itertools.izip(kmer_matches1,kmer_matches2): 
     pos_strand.append(match1.start()+1) 
     neg_strand.append(match2.start()+1) 

    with open('answer.gff3','w') as wfile: 
     while pos_strand and neg_strand: 
      if pos_strand[0]<neg_strand[0]: 
       start = pos_strand.popleft() 
       wfile.write(print_statement(start,'+')) 
      else: 
       start = neg_strand.popleft() 
       wfile.write(print_statement(start,'-')) 

     for start in pos_strand: 
      wfile.write(print_statement(start,'+')) 
     for start in neg_strand: 
      wfile.write(print_statement(start,'-')) 

    return 'percent-GC = %s'%str(sum(sequence.count(gc) for gc in ["G","C"])/float(len(sequence))) 
+0

Я изначально использовал grep, потому что я думал, что это быстрее, чем чтение всего файла через python. Неужели я ошибаюсь? – lstbl

+1

@lstbl: для действительно огромных файлов, в которых фильтрация будет устранена, большая часть входных данных может сэкономить немного, но вряд ли это будет иметь большое значение; самым большим узким местом для простых фильтров, таких как часто, является ввод-вывод, а не скорость обработки. Тем не менее, обертывание его в 'bash' бессмысленно и добавляет дополнительные накладные расходы (уменьшая малую прибыль, которую вы можете получить). Прыгая прямо на «grep» без тестирования, вы подписались на более сложный и хрупкий код. Если у вас нет убедительных тестов производительности, показывающих необходимость, простой и надежный всегда должен быть вашим первым выбором. – ShadowRanger

+2

@lstbl: Если 'grep' действительно дает преимущество, вы все равно хотите избежать временного файла. Используя 'filterlines = subprocess.check_output (['fgrep', '>', 'S288C_R64.fasta']). Splitlines()' предоставит вам те же выходные строки, которые будут переданы в ваше понимание списка, и сделайте это как одиночный запуск программы, отсутствие оболочки, отсутствие записи на диск, чтение и удаление файла ('check_output' выполняет прямое выполнение« stdout »подпроцесса, заменяя относительно медленные дисковые операции ввода-вывода с прямой связью каналов, используя в буферах памяти). – ShadowRanger

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