<p>I figured it out:</p>
<pre class="lang-python prettyprint-override"><code>from Bio import SeqIO
#import pprint
import textwrap

my_id_file     = open('sample_files2/fasta_id_records.txt','r')
my_fasta_file  = open('sample_files2/fasta_file.fasta','r')
result_file    = open('sample_files2/results.fasta', &quot;w&quot;)

my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'

#pprint.pprint(my_dictionary)
for seq_record in SeqIO.parse(my_fasta_file, &quot;fasta&quot;):
    if seq_record.id in my_dictionary:      
        #use this line to write standard fasta record using SeqIO.write
        SeqIO.write(seq_record, result_file, &quot;fasta&quot;)

my_fasta_file.close()
my_id_file.close()
result_file.close()
</code></pre>

CC BY-SA 4.0
2023-01-21T22:13:32.863Z
I'm not 100% sure you can because that will be taken care within SeqIO.write(). The obvious `seq_record.seq = textwrap.fill(str(seq_record.seq) , width=60)` is unlikely to work.
M__
CC BY-SA 4.0
2023-01-21T22:14:59.927Z
The only way to do it is within a straight write to disk in you first code ... but (obviously) write rather than print.
M__
CC BY-SA 4.0
2023-01-22T12:00:18.793Z
it wraps to 60 by default in Biopython 1.8 at least, if saves as 'fasta-2line' uses a single line for the seq
pippo1980
CC BY-SA 4.0
2023-01-21T19:20:38.793Z
2023-01-21T19:20:38.793Z
Supertech
<p>You could instead pass in a generator that yields <a href="https://biopython.org/wiki/SeqRecord" rel="nofollow noreferrer">SeqRecords</a>. This avoids storing the entire list of  sequences in memory and is usually the way to go assuming that you need to handle large files containing thousands of records. This example use a generator expression, which is a bit like a list comprehension, but instead of creating a list, it creates a generator:</p>
<pre><code>import argparse
import contextlib
import pathlib
import sys

from Bio import SeqIO
</code></pre>
<pre><code>def get_argument_parser():

    parser = argparse.ArgumentParser()

    parser.add_argument(
        &quot;fasta_file&quot;,
        type=pathlib.Path,
        metavar='FILE',
        help=&quot;Extract sequence records from FILE&quot;,
    )
    parser.add_argument(
        &quot;ids_file&quot;,
        type=pathlib.Path,
        metavar='FILE',
        help=&quot;Sequence record IDs/names to extract, one per line&quot;,
    )
    parser.add_argument(
        &quot;-o&quot;,
        &quot;--output&quot;,
        type=pathlib.Path,
        metavar='FILE',
        default=&quot;-&quot;,
        help=&quot;Write extracted sequences to FILE (default: stdout)&quot;,
    )
    parser.add_argument(
        &quot;-f&quot;,
        &quot;--force&quot;,
        action='store_true',
        help=&quot;Overwrite the output file if it exists&quot;,
    )

    return parser
</code></pre>
<pre><code>def main():

    parser = get_argument_parser()
    args = parser.parse_args()

    with contextlib.ExitStack() as stack:

        ids_file = stack.enter_context(open(args.ids_file))
        fasta_file = stack.enter_context(open(args.fasta_file))

        if args.output != '-':
            out = stack.enter_context(open(args.output, 'w' if args.force else 'x'))
        else:
            out = sys.stdout

        record_ids = {line.rstrip('\n') for line in ids_file}

        fasta = SeqIO.parse(fasta_file, &quot;fasta&quot;)
        records = (rec for rec in fasta if rec.id in record_ids)

        SeqIO.write(records, out, &quot;fasta&quot;)

if __name__ == &quot;__main__&quot;:
    main()
</code></pre>

CC BY-SA 4.0
2023-01-22T12:59:41.647Z
cool never eard about ExitStack till now https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack
pippo1980
CC BY-SA 4.0
2023-01-22T13:03:26.013Z
A better description about what it does is here https://www.rath.org/on-the-beauty-of-pythons-exitstack.html @pippo1980
M__
CC BY-SA 4.0
2023-01-22T13:11:22.750Z
I think I need to ask another question on this code. It's certainly professional code. What I'm wondering is how the if-condition tuple comprehension is a generator because thats the "workhorse" of the code.
M__
CC BY-SA 4.0
2023-01-22T13:21:45.870Z
@M__ The parentheses just make it a generator expression. Brackets would have made it a list comprehension: https://peps.python.org/pep-0289/
Steve
CC BY-SA 4.0
2023-01-22T16:17:07.647Z
@Steve, gave me a code to study.
Supertech
CC BY-SA 4.0
2023-01-22T12:21:28.767Z
2023-01-22T13:02:31.890Z
2023-01-22T13:02:31.890Z
Steve
<p>my attempt at changing the way Biopython formats fasta file sequence width,
read into code to figure out standard behaviour:</p>
<pre><code>from Bio import SeqIO, __version__
#import pprint
# import textwrap

print('Biopython version : ' , __version__)

# my_id_file     = open('sample_files2/fasta_id_records.txt','r')
# my_fasta_file  = open('sample_files2/fasta_file.fasta','r')
#result_file    = open('sample_files2/results.fasta', &quot;w&quot;)
### CHANGED TO:
    
my_id_file     = open('fasta_id_records.txt','r')
my_fasta_file  = open('fasta_file.fasta','r')
result_file    = open('results.fasta', &quot;w&quot;)


my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'

#expected lenght of sequences in my fasta
length = 10

#pprint.pprint(my_dictionary)
for seq_record in SeqIO.parse(my_fasta_file, &quot;fasta&quot;):
    if seq_record.id in my_dictionary:      
        
        
        ########################################################################################
        #use this line to write standard fasta record using SeqIO.write
        
        # SeqIO.write(seq_record, result_file, &quot;fasta-2line&quot;) # writes fasta in 2 line format
        
        # SeqIO.write(seq_record, result_file, &quot;fasta&quot;) # writes fasta with width of 60 as standard biopython format
        
        ### NOT POSSIBLE !!!!!!!!!!!!
        # seq_record.seq = textwrap.fill(seq_record.seq , width=10) ### --&gt; AttributeError: 'Seq' object has no attribute 'expandtabs'
        
        # print(seq_record.seq, type(seq_record.seq), dir(seq_record.seq))
        
        sequence = str(seq_record.seq)
        
        result_file.write('&gt;'+seq_record.id+'\n')
        
        while len(sequence) &gt; 0:
            result_file.write(sequence[:length]+'\n') 
            sequence = sequence[length:]
        result_file.write('\n')
        
        
        ### if you try to add EOL inside seq_record.seq of course you get 
        ### TypeError: SeqRecord (id=seq1) has an invalid sequence.
        # SeqIO.write(seq_record, result_file, &quot;fasta&quot;) # writes fasta with sequence width as 60   !!!! TypeError: SeqRecord (id=seq1) has an invalid sequence.

my_fasta_file.close()
my_id_file.close()
result_file.close()
</code></pre>
<p>input files :</p>
<p><code>fasta_id_records.txt</code>:</p>
<pre><code>seq1
seq2
seq3
</code></pre>
<p><code> fasta_file.fasta</code>:</p>
<pre><code>&gt;seq0
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
&gt;seq1
TTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTT
&gt;seq3
CCCCCCCCCCCCCCCCCGGGGGGGGGGGGGGGGGGGGGGGGGGGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
</code></pre>
<p>output file:</p>
<p><code>v </code>:</p>
<pre><code>&gt;seq1
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTT

&gt;seq3
CCCCCCCCCC
CCCCCCCGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
G


</code></pre>

CC BY-SA 4.0
2023-01-22T12:53:39.803Z
2023-01-22T13:01:45.073Z
2023-01-22T13:01:45.073Z
pippo1980
<p><strong>Update:</strong>
Biopython document says that &quot;Bio.SeqIO.FastaIO.FastaWriter&quot; class is obsolete. Now my question becomes how to I use <code>Bio.SeqIO.write()</code> fucntion do achive the same thing I asked.</p>
<p>I use the following code to extract specific FASTA records from a file based on a list of FASTA IDs given in another file. The script works just fine. However, I want to able to write the results using &quot;Bio.SeqIO.FastaIO.FastaWriter&quot; class into a file instead of Python's print or write function. How can I do that in my last if statement?</p>
<pre class="lang-python prettyprint-override"><code>from Bio import SeqIO
#import pprint
import textwrap

my_id_file     = open('sample_files2/fasta_id_records.txt','r')
my_fasta_file  = open('sample_files2/fasta_file.fasta','r')

my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'
#pprint.pprint(my_dictionary)

for seq_record in SeqIO.parse(my_fasta_file, &quot;fasta&quot;):
    if seq_record.id in my_dictionary:
        sequence = str(seq_record.seq)
        fasta_record = textwrap.fill(sequence, width=60)
        print(f&quot;&gt;{seq_record.id}\n{fasta_record}&quot;)

my_fasta_file.close()
my_id_file.close()
</code></pre>

CC BY-SA 4.0
2023-01-22T18:57:55.673Z
I was considering modifying the title. I am glad you edited it @gringer. Thank you.
Supertech
<python><fasta><biopython>
How to write FASTA records using "Bio.SeqIO.write()"
# How to write FASTA records using "Bio.SeqIO.write()"

(Asked by: username_0 on 2023-01-21)

Update:
Biopython document says that "Bio.SeqIO.FastaIO.FastaWriter" class is obsolete. Now my question becomes how to I use Bio.SeqIO.write() fucntion do achive the same thing I asked.
I use the following code to extract specific FASTA records from a file based on a list of FASTA IDs given in another file. The script works just fine. However, I want to able to write the results using "Bio.SeqIO.FastaIO.FastaWriter" class into a file instead of Python's print or write function. How can I do that in my last if statement?
from Bio import SeqIO
#import pprint
import textwrap

my_id_file     = open('sample_files2/fasta_id_records.txt','r')
my_fasta_file  = open('sample_files2/fasta_file.fasta','r')

my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'
#pprint.pprint(my_dictionary)

for seq_record in SeqIO.parse(my_fasta_file, "fasta"):
    if seq_record.id in my_dictionary:
        sequence = str(seq_record.seq)
        fasta_record = textwrap.fill(sequence, width=60)
        print(f">{seq_record.id}\n{fasta_record}")

my_fasta_file.close()
my_id_file.close()

**Tags:** python, fasta, biopython
> **Comments:**
> **username_0**: I was considering modifying the title. I am glad you edited it @gringer. Thank you.  

---

## 3 answers

### Answer by username_0 on 2023-01-21. Score: 4

I figured it out:
from Bio import SeqIO
#import pprint
import textwrap

my_id_file     = open('sample_files2/fasta_id_records.txt','r')
my_fasta_file  = open('sample_files2/fasta_file.fasta','r')
result_file    = open('sample_files2/results.fasta', "w")

my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'

#pprint.pprint(my_dictionary)
for seq_record in SeqIO.parse(my_fasta_file, "fasta"):
    if seq_record.id in my_dictionary:      
        #use this line to write standard fasta record using SeqIO.write
        SeqIO.write(seq_record, result_file, "fasta")

my_fasta_file.close()
my_id_file.close()
result_file.close()

> **Comments:**
> **username_1**: I'm not 100% sure you can because that will be taken care within SeqIO.write(). The obvious `seq_record.seq = textwrap.fill(str(seq_record.seq) , width=60)` is unlikely to work.  
> **username_1**: The only way to do it is within a straight write to disk in you first code ... but (obviously) write rather than print.  
> **username_2**: it wraps to 60 by default in Biopython 1.8 at least, if saves as 'fasta-2line' uses a single line for the seq  

---

### Answer by username_3 on 2023-01-22. Score: 2

You could instead pass in a generator that yields SeqRecords. This avoids storing the entire list of  sequences in memory and is usually the way to go assuming that you need to handle large files containing thousands of records. This example use a generator expression, which is a bit like a list comprehension, but instead of creating a list, it creates a generator:
import argparse
import contextlib
import pathlib
import sys

from Bio import SeqIO

def get_argument_parser():

    parser = argparse.ArgumentParser()

    parser.add_argument(
        "fasta_file",
        type=pathlib.Path,
        metavar='FILE',
        help="Extract sequence records from FILE",
    )
    parser.add_argument(
        "ids_file",
        type=pathlib.Path,
        metavar='FILE',
        help="Sequence record IDs/names to extract, one per line",
    )
    parser.add_argument(
        "-o",
        "--output",
        type=pathlib.Path,
        metavar='FILE',
        default="-",
        help="Write extracted sequences to FILE (default: stdout)",
    )
    parser.add_argument(
        "-f",
        "--force",
        action='store_true',
        help="Overwrite the output file if it exists",
    )

    return parser

def main():

    parser = get_argument_parser()
    args = parser.parse_args()

    with contextlib.ExitStack() as stack:

        ids_file = stack.enter_context(open(args.ids_file))
        fasta_file = stack.enter_context(open(args.fasta_file))

        if args.output != '-':
            out = stack.enter_context(open(args.output, 'w' if args.force else 'x'))
        else:
            out = sys.stdout

        record_ids = {line.rstrip('\n') for line in ids_file}

        fasta = SeqIO.parse(fasta_file, "fasta")
        records = (rec for rec in fasta if rec.id in record_ids)

        SeqIO.write(records, out, "fasta")

if __name__ == "__main__":
    main()

> **Comments:**
> **username_2**: cool never eard about ExitStack till now https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack  
> **username_1**: A better description about what it does is here https://www.rath.org/on-the-beauty-of-pythons-exitstack.html @pippo1980  
> **username_1**: I think I need to ask another question on this code. It's certainly professional code. What I'm wondering is how the if-condition tuple comprehension is a generator because thats the "workhorse" of the code.  
> **username_3**: @M__ The parentheses just make it a generator expression. Brackets would have made it a list comprehension: https://peps.python.org/pep-0289/  
> **username_0**: @Steve, gave me a code to study.  

---

### Answer by username_2 on 2023-01-22. Score: 2

my attempt at changing the way Biopython formats fasta file sequence width,
read into code to figure out standard behaviour:
from Bio import SeqIO, __version__
#import pprint
# import textwrap

print('Biopython version : ' , __version__)

# my_id_file     = open('sample_files2/fasta_id_records.txt','r')
# my_fasta_file  = open('sample_files2/fasta_file.fasta','r')
#result_file    = open('sample_files2/results.fasta', "w")
### CHANGED TO:
    
my_id_file     = open('fasta_id_records.txt','r')
my_fasta_file  = open('fasta_file.fasta','r')
result_file    = open('results.fasta', "w")


my_dictionary = {} # fasta IDs are keys, value can be anything.
for line in my_id_file:
    my_dictionary[line[:-1]] = 'value'

#expected lenght of sequences in my fasta
length = 10

#pprint.pprint(my_dictionary)
for seq_record in SeqIO.parse(my_fasta_file, "fasta"):
    if seq_record.id in my_dictionary:      
        
        
        ########################################################################################
        #use this line to write standard fasta record using SeqIO.write
        
        # SeqIO.write(seq_record, result_file, "fasta-2line") # writes fasta in 2 line format
        
        # SeqIO.write(seq_record, result_file, "fasta") # writes fasta with width of 60 as standard biopython format
        
        ### NOT POSSIBLE !!!!!!!!!!!!
        # seq_record.seq = textwrap.fill(seq_record.seq , width=10) ### --> AttributeError: 'Seq' object has no attribute 'expandtabs'
        
        # print(seq_record.seq, type(seq_record.seq), dir(seq_record.seq))
        
        sequence = str(seq_record.seq)
        
        result_file.write('>'+seq_record.id+'\n')
        
        while len(sequence) > 0:
            result_file.write(sequence[:length]+'\n') 
            sequence = sequence[length:]
        result_file.write('\n')
        
        
        ### if you try to add EOL inside seq_record.seq of course you get 
        ### TypeError: SeqRecord (id=seq1) has an invalid sequence.
        # SeqIO.write(seq_record, result_file, "fasta") # writes fasta with sequence width as 60   !!!! TypeError: SeqRecord (id=seq1) has an invalid sequence.

my_fasta_file.close()
my_id_file.close()
result_file.close()

input files :
fasta_id_records.txt:
seq1
seq2
seq3

 fasta_file.fasta:
>seq0
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>seq1
TTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTT
>seq3
CCCCCCCCCCCCCCCCCGGGGGGGGGGGGGGGGGGGGGGGGGGGGCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG

output file:
v :
>seq1
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTTTTTTTTT
TTT

>seq3
CCCCCCCCCC
CCCCCCCGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCC
CCCCCCCCCG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
GGGGGGGGGG
G


---

