Changing the record id in a FASTA file using BioPython I have the following FASTA file, original.fasta:

&gt;foo
GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA


I need to change the record id from foo to bar, so I wrote the following code:

from Bio import SeqIO

original_file = r"path\to\original.fasta"
corrected_file = r"path\to\corrected.fasta"

with open(original_file) as original, open(corrected_file, 'w') as corrected:
    records = SeqIO.parse(original_file, 'fasta')
    for record in records:
        print record.id             # prints 'foo'
        if record.id == 'foo':
            record.id = 'bar'
        print record.id             # prints 'bar' as expected
        SeqIO.write(record, corrected, 'fasta')


We printed the record id before and after the change, and get the expected result. We can even doublecheck by reading in the corrected file again with BioPython and printing out the record id:

with open(corrected_file) as corrected:
    for record in SeqIO.parse(corrected, 'fasta'):
        print record.id                  # prints 'bar', as expected


However, if we open the corrected file in a text editor, we see that the record id is not bar but  bar foo:

&gt;bar foo
GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA


We can confirm that this is what is written to the file if we read the file using plain Python:

with open(corrected_file) as corrected:
    print corrected.readlines()[0][1:] # prints 'bar foo'


Is this a bug in BioPython? And if not, what did I do wrong and how do I change the record id in a FASTA file using BioPython?
If I use SeqIO.parse(filehandle, 'fasta') to parse a FASTA file, then it will return a SeqRecord object where the id and name are the first word (everything before the first whitespace) of the line beginning with &gt; and the description is the complete line (all not including the initial &gt;). (This behaviour can overruled by providing a custom title2ids function).

So, if I for example have a original.fasta file like:

&gt;Lorem|ipsum&gt;dolor sit amet
GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA


Then I will get:

&gt;&gt;&gt; from Bio import SeqIO
&gt;&gt;&gt; path = r'C:\path\to\original.fasta'
&gt;&gt;&gt; records = SeqIO.parse(open(path), 'fasta')
&gt;&gt;&gt; record = next(records)
&gt;&gt;&gt; record.id
'Lorem|ipsum&gt;dolor'
&gt;&gt;&gt; record.name
'Lorem|ipsum&gt;dolor'
&gt;&gt;&gt; record.description
'Lorem|ipsum&gt;dolor sit amet'


So, what happens in my case when you do 

    if record.id == 'foo':
        record.id = 'bar'


is that the record.id is successfully changed from foo to bar, but that the record.description is not changed and stays foo. That's why, when the FASTA file is printed out, I see the described behaviour of 

&gt;bar foo
GCTCACACATAGTTGATGCAGATGTTGAATTCACTATGAGGTGGGAGGATGTAGGGCCA


So, the solution to my problem is to both change the id AND the description:

from Bio import SeqIO

original_file = r"path\to\original.fasta"
corrected_file = r"path\to\corrected.fasta"

with open(original_file) as original, open(corrected_file, 'w') as corrected:
    records = SeqIO.parse(original_file, 'fasta')
    for record in records:
        if record.id == 'foo':
            record.id = 'bar'
            record.description = 'bar'
        SeqIO.write(record, corrected, 'fasta')

with open(corrected_file) as corrected:
    records = SeqIO.parse(corrected, 'fasta')
    for record in records:
        print record.id             # prints bar
        print record.name           # prints bar
        print record.description    # prints bar