<jupyter_start><jupyter_text>**Biopython**06/05/2021 - Aula 3 **Capítulo 5 - Input/Output de sequências** **Tópicos abordados:** 5.1:  Parsing ou reading sequências5.2: Parsing sequências de arquivos compactados5.3: Parsing sequências da redeIremos discutir um pouco mais afundo o **módulo Bio.SeqIO**. O objetivo desse módulo é fornecer uma interface simples para trabalhar com diversos formatos de arquivo de sequência de maneira uniforme. Mas **ATENÇÃO**: esse módulo lida apenas com sequências que são **objetos SeqRecord** (o qual contém objetos Seq).Link do tutorial utilizado: http://biopython.org/DIST/docs/tutorial/Tutorial.pdf **Instalar a biblioteca Biopython e importar o módulo SeqIO:**<jupyter_code>!pip install biopython
from Bio import SeqIO<jupyter_output><empty_output><jupyter_text>**Podemos usar a função help() para obter informações sobre o módulo SeqIO:**<jupyter_code>help(SeqIO)<jupyter_output><empty_output><jupyter_text>**5.1 Parsing ou Reading Sequências** A função **Bio.SeqIO.parse()** é usada para ler dados de sequências como **objetos SeqRecord**. Esta função espera **dois argumentos**:1. O primeiro argumento é um **handle (identificador)** para ler os dados ou um nome de arquivo. Um handle é normalmente um arquivo aberto para leitura, mas pode ser a saída de um programa de linha de comando ou dados baixados da rede (consulte a Seção 5.3). 2. O segundo argumento é uma string com letras minúsculas especificando o **formato** da sequência - consulte http://biopython.org/wiki/SeqIO para obter uma lista completa dos formatos suportados.A função Bio.SeqIO.parse() **retorna um iterador** que fornece objetos SeqRecord. **Iteradores são normalmente usado em um "loop for"**. Às vezes, você se verá lidando com arquivos que contêm apenas **um único registro**. Para esta situação, use a função **Bio.SeqIO.read()** que recebe os mesmos argumentos. Desde que haja apenas um registro no arquivo, ele é retornado como um objeto SeqRecord. Caso contrário, uma exceção é gerada. **RESUMO:**SeqIO.parse() recede 2 argumentos:a) **handle** (identificador) ou o caminho do arquivob) **formato do arquivo** ("fasta", "genbank" ou "gb", "embl", "uniprot-xml", etc)Ficando assim: **SeqIO.parse(handle, formato)** **5.1.1 LENDO OS ARQUIVOS**:Em geral, Bio.SeqIO.parse() é usado para ler arquivos de sequência como **objetos SeqRecord** e é normalmente usado com um **loop for**. Irei utilizar arquivos nos formatos FASTA e GenBank.Baixar os exemplos: https://github.com/biopython/biopython/tree/master/Doc/examplesPara fazer o download dos exemplos:a) clique no exemplo desejadob) clique em Raw (lado direito da tela)c) clique com o botão direito e "Salvar como..." para salvar o arquivo<jupyter_code># iterador - FASTA
for record in SeqIO.parse("ls_orchid.fasta.txt", "fasta"):
  print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")
# iterador - GENBANK
for record in SeqIO.parse("ls_orchid.gbk.txt", "gb"):
  print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output><empty_output><jupyter_text>Usar list comprehension para extrair as IDs das sequências:<jupyter_code>IDs = []
for record in SeqIO.parse("ls_orchid.fasta.txt", "fasta"):
  IDs.append(record.id)
print(IDs)
# FASTA
ids = [record.id for record in SeqIO.parse("ls_orchid.fasta.txt", "fasta")]
print(ids)
# GENBANK
ids = [record.id for record in SeqIO.parse("ls_orchid.gbk.txt", "gb")]
print(ids)<jupyter_output>['Z78533.1', 'Z78532.1', 'Z78531.1', 'Z78530.1', 'Z78529.1', 'Z78527.1', 'Z78526.1', 'Z78525.1', 'Z78524.1', 'Z78523.1', 'Z78522.1', 'Z78521.1', 'Z78520.1', 'Z78519.1', 'Z78518.1', 'Z78517.1', 'Z78516.1', 'Z78515.1', 'Z78514.1', 'Z78513.1', 'Z78512.1', 'Z78511.1', 'Z78510.1', 'Z78509.1', 'Z78508.1', 'Z78507.1', 'Z78506.1', 'Z78505.1', 'Z78504.1', 'Z78503.1', 'Z78502.1', 'Z78501.1', 'Z78500.1', 'Z78499.1', 'Z78498.1', 'Z78497.1', 'Z78496.1', 'Z78495.1', 'Z78494.1', 'Z78493.1', 'Z78492.1', 'Z78491.1', 'Z78490.1', 'Z78489.1', 'Z78488.1', 'Z78487.1', 'Z78486.1', 'Z78485.1', 'Z78484.1', 'Z78483.1', 'Z78482.1', 'Z78481.1', 'Z78480.1', 'Z78479.1', 'Z78478.1', 'Z78477.1', 'Z78476.1', 'Z78475.1', 'Z78474.1', 'Z78473.1', 'Z78472.1', 'Z78471.1', 'Z78470.1', 'Z78469.1', 'Z78468.1', 'Z78467.1', 'Z78466.1', 'Z78465.1', 'Z78464.1', 'Z78463.1', 'Z78462.1', 'Z78461.1', 'Z78460.1', 'Z78459.1', 'Z78458.1', 'Z78457.1', 'Z78456.1', 'Z78455.1', 'Z78454.1', 'Z78453.1', 'Z78452.1', 'Z78451.1', 'Z78450.1', 'Z7[...]<jupyter_text>**Fazer download do GenBank:** formato FASTAhttps://www.ncbi.nlm.nih.gov/nuccore/Z78533.1?report=fasta<jupyter_code># FASTA

# iterador
for record in SeqIO.parse("sequence.fasta", "fasta"):
  print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output>ID: Z78533.1    Tamanho: 740 nt<jupyter_text>formato GENBANKhttps://www.ncbi.nlm.nih.gov/nuccore/Z78533.1?report=genbank<jupyter_code># GENBANK

# iterador
for record in SeqIO.parse("sequence.gb", "gb"):
  print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output>ID: Z78533.1    Tamanho: 740 nt<jupyter_text>**5.1.2 ITERANDO SOBRE OS REGISTROS DO ARQUIVO**: Nos exemplos acima, usamos um **loop for** para iterar todos os registros um por um. Você pode usar o **loop for** com todos os tipos de objetos Python (incluindo listas, tuplas e strings) que suportam a iteração.O objeto retornado por Bio.SeqIO é na verdade um iterador que retorna objetos SeqRecord. Você consegue ver cada registro por vez, mas apenas uma vez. **O ponto positivo é que um iterador pode economizar memória ao lidar com arquivos grandes.**Em vez de usar um **loop for**, também pode usar a função **next()** em um iterador para percorrer as entradas.<jupyter_code>record_iterator = SeqIO.parse("ls_orchid.fasta.txt", "fasta")

# usar next() para ir iterando sequência por sequência
first_record = next(record_iterator)
print(first_record.id)
print(first_record.description)

print()

second_record = next(record_iterator)
print(second_record.id)
print(second_record.description)<jupyter_output>gi|2765658|emb|Z78533.1|CIZ78533
gi|2765658|emb|Z78533.1|CIZ78533 C.irapeanum 5.8S rRNA gene and ITS1 and ITS2 DNA

gi|2765657|emb|Z78532.1|CCZ78532
gi|2765657|emb|Z78532.1|CCZ78532 C.californicum 5.8S rRNA gene and ITS1 and ITS2 DNA<jupyter_text>Observe que se você tentar usar **next()** e não houver mais resultados, você obterá a exceção "StopIteration". Usar next() para extrair apenas a primeira sequência:<jupyter_code>first_record = next(SeqIO.parse("ls_orchid.fasta.txt", "fasta"))
print(first_record)<jupyter_output>ID: gi|2765658|emb|Z78533.1|CIZ78533
Name: gi|2765658|emb|Z78533.1|CIZ78533
Description: gi|2765658|emb|Z78533.1|CIZ78533 C.irapeanum 5.8S rRNA gene and ITS1 and ITS2 DNA
Number of features: 0
Seq('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGATGAGACCGTGG...CGC')<jupyter_text>**Para arquivos que contenham apenas 1 registro (1 record), podemos utilizar o "SeqIO.read()":** Vamos fazer um teste: usar o SeqIO.parse() para ler um arquivo que contém apenas 1 registro. Quando usamos o 'parse', é retornado um iterador. Por isso não conseguimos acessar diretamente os atributos do objeto:<jupyter_code># Observe o ERRO gerado ao tentar acessar os atributos do iterador
record = SeqIO.parse("sequence.fasta", "fasta")
print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output><empty_output><jupyter_text>Para corrigir isso, podemos usar a função next():<jupyter_code># Use next() para driblar o erro
record = next(SeqIO.parse("sequence.fasta", "fasta"))
print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output>ID: Z78533.1    Tamanho: 740 nt<jupyter_text>Porém, a melhor maneira para ler arquivos que contenham apenas 1 registro é com o **SeqIO.read()**, pois retorna um objeto em que podemos acessar os atributos:<jupyter_code># SeqIO.read()
record = SeqIO.read("sequence.fasta", "fasta")
print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output>ID: Z78533.1    Tamanho: 740 nt<jupyter_text>**5.1.3 CRIANDO UMA LISTA DOS REGISTROS**: SeqIO.parse() retorna um iterador, assim você tem acesso aos registros um a um, porém, pode ser que você precise acessar um registro em uma dada ordem. Para isso, temos que transformar o iterador em uma **lista**.<jupyter_code># usar list()
records = list(SeqIO.parse("ls_orchid.fasta.txt", "fasta"))

print(f"Existem {len(records)} registros")
first_record = records[0]
print("Primero registro:")
print(f"ID: {first_record.id}")
print(f"Tamanho: {len(first_record.seq)}")

print()
print("Último registro:")
last_record = records[-1] 
print(f"ID: {last_record.id}")
print(f"Tamanho: {len(last_record.seq)}")<jupyter_output>Primero registro:
ID: gi|2765658|emb|Z78533.1|CIZ78533
Tamanho: 740

Último registro:
ID: gi|2765564|emb|Z78439.1|PBZ78439
Tamanho: 592<jupyter_text>É claro que podemos um **loop for** com uma lista de objetos SeqRecord. Usar uma lista é muito mais flexíveldo que um iterador (por exemplo, você pode determinar o número de registros do comprimento da lista), masprecisa de mais memória porque irá manter todos os registros na memória de uma vez. **5.1.4 EXTRAINDO DADOS**: O objeto SeqRecord e suas estruturas de anotação são descritos mais detalhadamente no Capítulo 4. Como um exemplo de como as anotações são armazenadas, veremos a saída da análise do **primeiro registro no arquivo GenBank**.<jupyter_code># GENBANK

# iterador
record_iterator = SeqIO.parse("ls_orchid.gbk.txt", "genbank")

# primeiro registro do arquivo
first_record = next(record_iterator)
print(first_record)<jupyter_output>ID: Z78533.1
Name: Z78533
Description: C.irapeanum 5.8S rRNA gene and ITS1 and ITS2 DNA
Number of features: 5
/molecule_type=DNA
/topology=linear
/data_file_division=PLN
/date=30-NOV-2006
/accessions=['Z78533']
/sequence_version=1
/gi=2765658
/keywords=['5.8S ribosomal RNA', '5.8S rRNA gene', 'internal transcribed spacer', 'ITS1', 'ITS2']
/source=Cypripedium irapeanum
/organism=Cypripedium irapeanum
/taxonomy=['Eukaryota', 'Viridiplantae', 'Streptophyta', 'Embryophyta', 'Tracheophyta', 'Spermatophyta', 'Magnoliophyta', 'Liliopsida', 'Asparagales', 'Orchidaceae', 'Cypripedioideae', 'Cypripedium']
/references=[Reference(title='Phylogenetics of the slipper orchids (Cypripedioideae: Orchidaceae): nuclear rDNA ITS sequences', ...), Reference(title='Direct Submission', ...)]
Seq('CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGATGAGACCGTGG...CGC')<jupyter_text>Isso fornece um resumo legível da maioria dos dados de anotação para o SeqRecord. Para este exemplo, vamos usar o atributo **.annotations**, que é um dicionário Python. O conteúdo deste dicionário de anotações foi mostrado quando imprimimos o registro acima. Você também pode imprimi-losdiretamente:<jupyter_code># imprimir o dicionário 'annotations'
print(first_record.annotations)
# chaves
print(first_record.annotations.keys())
# valores
print(first_record.annotations.values())<jupyter_output>dict_values(['DNA', 'linear', 'PLN', '30-NOV-2006', ['Z78533'], 1, '2765658', ['5.8S ribosomal RNA', '5.8S rRNA gene', 'internal transcribed spacer', 'ITS1', 'ITS2'], 'Cypripedium irapeanum', 'Cypripedium irapeanum', ['Eukaryota', 'Viridiplantae', 'Streptophyta', 'Embryophyta', 'Tracheophyta', 'Spermatophyta', 'Magnoliophyta', 'Liliopsida', 'Asparagales', 'Orchidaceae', 'Cypripedioideae', 'Cypripedium'], [Reference(title='Phylogenetics of the slipper orchids (Cypripedioideae: Orchidaceae): nuclear rDNA ITS sequences', ...), Reference(title='Direct Submission', ...)]])<jupyter_text>Extrair o nome da espécie:<jupyter_code># organism = nome científico
first_record.annotations["organism"]
# source = nome comum (aqui coincidiu de serem o mesmo nome)
first_record.annotations["source"]<jupyter_output><empty_output><jupyter_text>Extrair os nomes de todas as espécies:<jupyter_code># lista vazia
all_species = []

# iterador
for record in SeqIO.parse("ls_orchid.gbk.txt", "genbank"):
  all_species.append(record.annotations["organism"])

print(all_species)
print(len(all_species))<jupyter_output>['Cypripedium irapeanum', 'Cypripedium californicum', 'Cypripedium fasciculatum', 'Cypripedium margaritaceum', 'Cypripedium lichiangense', 'Cypripedium yatabeanum', 'Cypripedium guttatum', 'Cypripedium acaule', 'Cypripedium formosanum', 'Cypripedium himalaicum', 'Cypripedium macranthon', 'Cypripedium calceolus', 'Cypripedium segawai', 'Cypripedium parviflorum var. pubescens', 'Cypripedium reginae', 'Cypripedium flavum', 'Cypripedium passerinum', 'Mexipedium xerophyticum', 'Phragmipedium schlimii', 'Phragmipedium besseae', 'Phragmipedium wallisii', 'Phragmipedium exstaminodium', 'Phragmipedium caricinum', 'Phragmipedium pearcei', 'Phragmipedium longifolium', 'Phragmipedium lindenii', 'Phragmipedium lindleyanum', 'Phragmipedium sargentianum', 'Phragmipedium kaiteurum', 'Phragmipedium czerwiakowianum', 'Phragmipedium boissierianum', 'Phragmipedium caudatum', 'Phragmipedium warszewiczianum', 'Paphiopedilum micranthum', 'Paphiopedilum malipoense', 'Paphiopedilum delenatii', 'Paphiopedilum a[...]<jupyter_text>Extrair os nomes de todas as espécies com list comprehension:<jupyter_code>all_species = [record.annotations["organism"] for record in SeqIO.parse("ls_orchid.gbk.txt", "genbank")]

print(all_species)
print(len(all_species))<jupyter_output>['Cypripedium irapeanum', 'Cypripedium californicum', 'Cypripedium fasciculatum', 'Cypripedium margaritaceum', 'Cypripedium lichiangense', 'Cypripedium yatabeanum', 'Cypripedium guttatum', 'Cypripedium acaule', 'Cypripedium formosanum', 'Cypripedium himalaicum', 'Cypripedium macranthon', 'Cypripedium calceolus', 'Cypripedium segawai', 'Cypripedium parviflorum var. pubescens', 'Cypripedium reginae', 'Cypripedium flavum', 'Cypripedium passerinum', 'Mexipedium xerophyticum', 'Phragmipedium schlimii', 'Phragmipedium besseae', 'Phragmipedium wallisii', 'Phragmipedium exstaminodium', 'Phragmipedium caricinum', 'Phragmipedium pearcei', 'Phragmipedium longifolium', 'Phragmipedium lindenii', 'Phragmipedium lindleyanum', 'Phragmipedium sargentianum', 'Phragmipedium kaiteurum', 'Phragmipedium czerwiakowianum', 'Phragmipedium boissierianum', 'Phragmipedium caudatum', 'Phragmipedium warszewiczianum', 'Paphiopedilum micranthum', 'Paphiopedilum malipoense', 'Paphiopedilum delenatii', 'Paphiopedilum a[...]<jupyter_text>Conseguimos extrair essas informações facilmente porque os arquivos no formato GenBank possuem as anotações padronizadas. Mas isso não acontece com os arquivos FASTA. Repare abaixo que o nome da espécie está contido na descrição. Então temos que escrever um código se quisermos extrair apenas os nomes das espécies:<jupyter_code># FASTA
first_record = next(SeqIO.parse("ls_orchid.fasta.txt", "fasta"))
print(first_record)
# nome da espécie está na descrição
print(first_record.description)
# pegar apenas o nome --> fazer um split() para separar cada palavra
print(first_record.description.split())
# o nome é o segundo elemento da lista
print(first_record.description.split()[1])
# salvar as espécies em uma lista
all_species = []
for record in SeqIO.parse("ls_orchid.fasta.txt", "fasta"):
  name = record.description.split()[1]
  all_species.append(name)

print(all_species)
print(len(all_species))<jupyter_output>['C.irapeanum', 'C.californicum', 'C.fasciculatum', 'C.margaritaceum', 'C.lichiangense', 'C.yatabeanum', 'C.guttatum', 'C.acaule', 'C.formosanum', 'C.himalaicum', 'C.macranthum', 'C.calceolus', 'C.segawai', 'C.pubescens', 'C.reginae', 'C.flavum', 'C.passerinum', 'M.xerophyticum', 'P.schlimii', 'P.besseae', 'P.wallisii', 'P.exstaminodium', 'P.caricinum', 'P.pearcei', 'P.longifolium', 'P.lindenii', 'P.lindleyanum', 'P.sargentianum', 'P.kaiteurum', 'P.czerwiakowianum', 'P.boissierianum', 'P.caudatum', 'P.warszewiczianum', 'P.micranthum', 'P.malipoense', 'P.delenatii', 'P.armeniacum', 'P.emersonii', 'P.niveum', 'P.godefroyae', 'P.bellatulum', 'P.concolor', 'P.fairrieanum', 'P.druryi', 'P.tigrinum', 'P.hirsutissimum', 'P.barbigerum', 'P.henryanum', 'P.charlesworthii', 'P.villosum', 'P.exul', 'P.insigne', 'P.gratrixianum', 'P.primulinum', 'P.victoria', 'P.victoria', 'P.glaucophyllum', 'P.supardii', 'P.kolopakingii', 'P.sanderianum', 'P.lowii', 'P.dianthum', 'P.parishii', 'P.haynaldianum', 'P[...]<jupyter_text>Em geral, extrair informações da descrição do FASTA não é muito agradável. Se você conseguir suas sequências em um formato de arquivo bem anotado como GenBank ou EMBL, então este tipo de informação de anotação será muito mais fácil de lidar. **5.1.5 MODIFICANDO DADOS**:<jupyter_code>first_record = next(SeqIO.parse("ls_orchid.fasta.txt", "fasta"))
# modificar o ID
first_record.id
first_record.description
# modificar diretamente no atributo
first_record.id = "new_id"
print(first_record.id)
# alterar a descrição
first_record.description
# não esquecer de colocar espaço entre o ID e a descrição
first_record.description = first_record.id + " " + "new_description_here"
print(first_record.description)
print(first_record.format("fasta"))<jupyter_output>>new_id new_description_here
CGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATTGATGAGACCGTGGAATAAA
CGATCGAGTGAATCCGGAGGACCGGTGTACTCAGCTCACCGGGGGCATTGCTCCCGTGGT
GACCCTGATTTGTTGTTGGGCCGCCTCGGGAGCGTCCATGGCGGGTTTGAACCTCTAGCC
CGGCGCAGTTTGGGCGCCAAGCCATATGAAAGCATCACCGGCGAATGGCATTGTCTTCCC
CAAAACCCGGAGCGGCGGCGTGCTGTCGCGTGCCCAATGAATTTTGATGACTCTCGCAAA
CGGGAATCTTGGCTCTTTGCATCGGATGGAAGGACGCAGCGAAATGCGATAAGTGGTGTG
AATTGCAAGATCCCGTGAACCATCGAGTCTTTTGAACGCAAGTTGCGCCCGAGGCCATCA
GGCTAAGGGCACGCCTGCTTGGGCGTCGCGCTTCGTCTCTCTCCTGCCAATGCTTGCCCG
GCATACAGCCAGGCCGGCGTGGTGCGGATGTGAAAGATTGGCCCCTTGTGCCTAGGTGCG
GCGGGTCCAAGAGCTGGTGTTTTGATGGCCCGGAACCCGGCAAGAGGTGGACGGATGCTG
GCAGCAGCTGCCGTGCGAATCCCCCATGTTGTCGTGCTTGTCGGACAGGCAGGAGAACCC
TTCCGAACCCCAATGGAGGGCGGTTGACCGCCATTCGGATGTGACCCCAGGTCAGGCGGG
GGCACCCGCTGAGTTTACGC<jupyter_text>**5.2  Parsing sequências de arquivos comprimidos/compactados** Resumindo, podemos ler os arquivos de 3 maneiras:<jupyter_code># passando apenas o nome do arquivo/caminho
print(sum(len(r) for r in SeqIO.parse("ls_orchid.gbk.txt", "gb")))
print(sum(len(r) for r in SeqIO.parse("/content/ls_orchid.gbk.txt", "gb")))
# com 'with'
with open("ls_orchid.gbk.txt") as handle:
  print(sum(len(r) for r in SeqIO.parse(handle, "gb")))
# com 'open'
handle = open("ls_orchid.gbk.txt")

print(sum(len(r) for r in SeqIO.parse(handle, "gb")))

handle.close()<jupyter_output>67518<jupyter_text>Mas e se tivermos um arquivo compactado, como o formato **gzip**? Esse formato é bem comum em Linux. Existe uma variante gzip (GNU Zip) chamada BGZF (Blocked GNU Zip Format), que pode ser tratada como um arquivo gzip comum para leitura, mas tem vantagens para acesso aleatório posteriormente, que é abordado naSeção 5.4.4.Além do gzip, há também o formato **bz2**. Podemos usar Python para abrir esses tipos de arquivos: Download dos exemplos: https://github.com/biopython/biopython/tree/master/Doc/examples<jupyter_code>import gzip
with gzip.open("ls_orchid.gbk.gz", "rt") as handle:
  print(sum(len(r) for r in SeqIO.parse(handle, "gb")))
import bz2
with bz2.open("ls_orchid.gbk.bz2", "rt") as handle:
  print(sum(len(r) for r in SeqIO.parse(handle, "gb")))<jupyter_output>67518<jupyter_text>**5.3  Parsing sequências da rede** Nas seções anteriores, vimos como analisar dados de sequência de um arquivo (usando o nome/caminho do arquivo ou o handle) ede arquivos compactados (usando um handle). Aqui, usaremos Bio.SeqIO com outro tipo de handle, uma conexão de rede, para baixar e analisar sequências da Internet.Observe que só porque você pode baixar dados de sequência e analisá-los em um objeto SeqRecord de uma só veznão significa que seja uma boa ideia. Em geral, você provavelmente deve baixar as sequências uma vez e salvá-lasem um arquivo para reutilização. **5.3.1 PARSING REGISTROS GENBANK DA REDE**: A seção 9.6 fala sobre a interface Entrez EFetch em mais detalhes, mas por enquanto vamos apenas conectar aoNCBI e obter algumas sequências de *Opuntia* (prickly-pear) do GenBank usando seus números GI.Em primeiro lugar, vamos buscar **(fetch)** apenas um registro. Se você não precisa das anotações e recursos,um arquivo FASTA é uma boa escolha, pois são compactos. Agora lembre-se, quando você espera que o **loop for** contenhaapenas um registro, use a função SeqIO.read():<jupyter_code>from Bio import Entrez
# FASTA - 1 registro
Entrez.email = "<EMAIL>"

with Entrez.efetch(db="nucleotide", rettype="fasta", retmode="text", id="6273291") as handle:
  record = SeqIO.read(handle, "fasta")

print(f"ID: {record.id}, Features: {len(record.features)}")
# GeNBANK - 1 registro
Entrez.email =  "<EMAIL>"

with Entrez.efetch(db="nucleotide", rettype="gb", retmode="text", id="6273291") as handle:
  record = SeqIO.read(handle, "gb") # usar "gb" como apelido para "genbank"
print(f"ID: {record.id}, Features: {len(record.features)}")

# GeNBANK - 2 ou + registros
Entrez.email =  "<EMAIL>"

with Entrez.efetch(db="nucleotide", rettype="gb", retmode="text", id="6273291, 6273290, 6273289") as handle:
  for record in SeqIO.parse(handle, "gb"):
    print(record.id, record.description[:50], "...")
    print(f"""Tamanho da sequência: {len(record.seq)}, Features: {len(record.features)}, 
    Fonte: {record.annotations["source"]}\n""")<jupyter_output>AF191665.1 Opuntia marenae rpl16 gene; chloroplast gene for c ...
Tamanho da sequência: 902, Features: 3, 
    Fonte: chloroplast Grusonia marenae

AF191664.1 Opuntia clavata rpl16 gene; chloroplast gene for c ...
Tamanho da sequência: 899, Features: 3, 
    Fonte: chloroplast Grusonia clavata

AF191663.1 Opuntia bradtiana rpl16 gene; chloroplast gene for ...
Tamanho da sequência: 899, Features: 3, 
    Fonte: chloroplast Grusonia bradtiana<jupyter_text>**5.3.2 PARSING REGISTROS SWISSPROT DA REDE**: Agora vamos usar um handle para baixar um arquivo SwissProt do ExPASy, algo abordado com mais detalhes no Capítulo 10. Como mencionado acima, quando você espera que o identificador contenha apenas um registro, use a função SeqIO.read():<jupyter_code>from Bio import ExPASy
with ExPASy.get_sprot_raw("O23729") as handle:
  record = SeqIO.read(handle, "swiss")
  print(record.id)
  print(record.name)
  print(record.description)
  print(repr(record.seq))
  print(f"Tamanho: {len(record.seq)}")
  print(record.annotations["keywords"])<jupyter_output>O23729
CHS3_BROFI
RecName: Full=Chalcone synthase 3; EC=2.3.1.74; AltName: Full=Naringenin-chalcone synthase 3;
Seq('MAPAMEEIRQAQRAEGPAAVLAIGTSTPPNALYQADYPDYYFRITKSEHLTELK...GAE')
Tamanho: 394
['Acyltransferase', 'Flavonoid biosynthesis', 'Transferase']<jupyter_text>**EXTRA: ler arquivo do GitHub:** Link: https://github.com/biopython/biopython/blob/master/Doc/examples/ls_orchid.fasta(copiar o link Raw do exemplo desejado)<jupyter_code># Para ler links da web, temos que importar o 'requests'
import requests

# Para transformar os registros do arquivo em objeto, utilizamos StringIO
from io import StringIO
# passar o link raw 
link = "https://raw.githubusercontent.com/biopython/biopython/master/Doc/examples/ls_orchid.fasta"
leitura = requests.get(link).text
handle = StringIO(leitura)

record = next(SeqIO.parse(handle, "fasta"))
print(f"ID: {record.id}    Tamanho: {len(record.seq)} nt")<jupyter_output>ID: gi|2765658|emb|Z78533.1|CIZ78533    Tamanho: 740 nt
{'fraction_non_alphanumeric': 0.12775406372612427, 'fraction_numerical': 0.04285775880653646, 'mean_word_length': 6.607084289931125, 'pattern_counts': {'":': 1, '<': 81, '<?xml version=': 0, '>': 83, 'https://': 6, 'lorem ipsum': 0, 'www.': 2, 'xml': 1}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '454439', 'license': 'CC0-1.0', 'n_tokens_mistral': 9882, 'n_tokens_neox': 9045, 'n_words': 2222, 'path': 'estudo_de_biopython/Aula3_biopython.ipynb', 'repo_name': 'lconteville/grupo-estudo-bioinformatica', 'size': '23232'}