I have a file with protein sequences, all on a single line, like this:


I want to print all sequences between an M residue and a * that are at least 6 residues long, and I would like the output like this:


Where the first number after the underscore is the number found in as the first character of the sequence (it is the reading frame) and the second number is the sequence number. and the last number is the fragment number. So, since the 1st sequence starts with;

>Contig_1 1FFPMPQ

The name will be >Contig_1.1 and each fragment found will be >Contig_1.1.1, >Contig_1.1.2, ... , >Contig_1.1.N.

After implementing the suggestion in the answer below and escaping the * in my regular expression, my current code is:

import sys
import re

# parse record
my_protein = []
for line in myprotein:
    if not line.startswith('>'):
        header = line

# build sequence
my_pro = ''.join(my_protein)

# cleave sequence                                                                                                                                                                                                                                                        
peptides = re.findall(r'(M[A-Z]{6,}\*)', my_pro)

# build a formatted list
records = ["%sNo.%d\n%s\n" % (header, idx + 1, fragment) for idx, fragment in     enumerate(peptides)]

# print list
for record in records:
    sys.stdout.write("%s" % (record))

And it prints:


How can I change this to get my desired output format?

  • $\begingroup$ re.findall('M[A-Z]{6,}*', seq) $\endgroup$ May 1, 2018 at 15:01
  • 2
    $\begingroup$ My apologies. the back-slash in my code got stripped for some reason. Try re.findall('M[A-Z]{6,}\*', seq) $\endgroup$ May 1, 2018 at 15:24
  • 4
    $\begingroup$ Hi and welcome to the site! When posting this sort of question, please always include the errors you get. Telling us "this doesn't work" is really not very helpful, it is always better to explain how it fails. $\endgroup$
    – terdon
    May 1, 2018 at 15:47
  • $\begingroup$ Sorry for posting like that I just update my question so it would be great if you could help. Thanks $\endgroup$ May 1, 2018 at 16:30

1 Answer 1


The * character has a special meaning in regular expressions, it means "0 or more". So when you write {6,}*, the regex engine tries to apply the "0 or more" to the {6,*} and gets confused:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/re.py", line 222, in findall
    return _compile(pattern, flags).findall(string)
  File "/usr/lib/python3.6/re.py", line 301, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python3.6/sre_compile.py", line 562, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/lib/python3.6/sre_parse.py", line 855, in parse
    p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
  File "/usr/lib/python3.6/sre_parse.py", line 416, in _parse_sub
    not nested and not items))
  File "/usr/lib/python3.6/sre_parse.py", line 619, in _parse
    source.tell() - here + len(this))
sre_constants.error: multiple repeat at position 10

In order to use special characters literally, as simple strings, you need to escape them by adding a \ before them. So try:

import re
protein = re.findall('M[A-Z]{6,}\*',myprotein)

To get the output you asked for while reading from a file, you can do:

import sys
import re

proteinFile = sys.argv[1]

with open(proteinFile, 'r') as f:
    for line in f:
        ## Split the long input line into the list 'sequences'
        sequences = line.rstrip('\n').split('>')

        for i, k in list(enumerate(sequences)):
            ## Skip the first element which will be empty.
            ## there must be a pythonic way of doing this, but I'm
            ## a Perl hacker, so I don't know it.             
            if len(k) == 0:

            seqName, seq = k.split(' ')
            ## Get the frame
            frame = seq[0]
            ## Remove the frame from the sequence
            seq = seq[1:]
            # cleave sequence
            peptides = re.findall(r'(M[A-Z]{6,}\*)', seq)

            for idx, peptide in enumerate(peptides):
                print(">%s.%s.%d\n%s" % (seqName, frame, idx+1, peptide) )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.