2016-01-13 64 views
-2

我目前正在用python写一个需要多个标志的脚本。这是我第一次尝试这样的程序,并且我从bash脚本中得到了一个我不太明白的输出。例如,当我运行bash shell中的脚本:在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单行要求的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:对于真正的大文件,要完成的过滤消除了大部分输入,它可能会节省一点点,但这不太可能;这种简单过滤器最大的瓶颈往往是I/O,而不是处理速度。即便如此,将它封装在“bash”中也是毫无意义的,并增加了额外的开销(减少了你可能获得的一点收益)。没有测试就直接跳到'grep'意味着你已经注册了更复杂和更脆弱的代码。如果你没有引人注目的性能测试显示需求,简单而强大的应该永远是你的第一选择。 – ShadowRanger

+2

@lstbl:如果'grep'真的提供了一个好处,你仍然想避免临时文件。使用'filteredlines = subprocess.check_output(['fgrep','>','S288C_R64.fasta')).lineslines()'会得到相同的输出行来传递给你的列表理解,并将它作为一个单独的程序启动,没有外壳封装,不写入磁盘,读回和删除文件('check_output'直接从子进程的'stdout'中直接读取,用内存缓冲区中的直接管道通信替换相对较慢的磁盘I/O)。 – ShadowRanger