Je suis assez novice en Python et j'essaie de diviser un fichier texte dont les entrées sont constituées de deux lignes en lots de max. 400 objets.
Les données avec lesquelles je travaille sont des milliers de séquences au format FASTA (texte brut avec un en-tête, utilisé en bio-informatique) dont les entrées ressemblent à ceci :
>HORVU6Hr1G000325.5
PIPPPASHFHPHHQNPSAATQPLCAAMAPAAKKPPLKSSSSHNSAAGDAA
>HORVU6Hr1G000326.1
MVKFTAEELRGIMDKKNNIRNMSVIAHVD
...
Dans Biopython, il existe un analyseur SeqIO.parse qui permet d'accéder à ces données sous la forme d'un tableau d'objets composé d'ID et de chaînes de caractères, que je dois utiliser dans des parties ultérieures de mon code, et comme je dois être économe en mémoire, j'aimerais éviter de lire et d'analyser le fichier source plus de fois que nécessaire.
Dans le manuel de Biopython, il est recommandé de faire cela via un générateur, ce que j'utilise : https://biopython.org/wiki/Split_large_file
Cependant, j'utilise Python 3.7 alors que le code est en Python 2.x, il y a donc des changements nécessaires. J'ai modifié le fichier
entry = iterator.next()
en
entry = next(iterator)
mais je ne sais pas si c'est tout ce que je dois changer.
Voici le code :
def batch_iterator(iterator, batch_size=400):
"""Returns lists of length batch_size."""
entry = True # Make sure we loop once
while entry:
batch = []
while len(batch) < batch_size:
try:
entry = next(iterator)
except StopIteration:
entry = None
if entry is None:
# End of file
break
batch.append(entry)
if batch:
yield batch
while True:
bsequence = input("Please enter the full path to your FASTA file(e.g. c:\\folder1\\folder2\\protein.fasta):\n")
try:
fastafile = open(bsequence)
break
except:
print("File not found!\n")
record_iter = SeqIO.parse(fastafile,"fasta")
num = 0
for line in fastafile:
if line.startswith(">"):
num += 1
print("num=%i" % (num,))
if num > 400:
print("The specified file contains %i sequences. It's recommended to split the FASTA file into batches of max. 400 sequences.\n" % (num,))
while True:
decision = input("Do you wish to create batch files? (Original file will not be overwritten)\n(Y/N):")
if (decision == 'Y' or 'y'):
for i, batch in enumerate(batch_iterator(record_iter, 400), 1):
filename = "group_%i.fasta" % (i + 1)
with open(filename, "w") as handle:
count = SeqIO.write(batch, handle, "fasta")
print("Wrote %i records to %s" % (count, filename))
break
elif (decision == 'N' or 'n'):
break
else:
print('Invalid input\n')
...next part of the code
Lorsque j'exécute ce programme, après l'invite Y/N, même si je tape Y, le programme passe à la partie suivante de mon code sans créer de nouveau fichier. Le débogueur affiche ce qui suit :
Do you wish to create batch files? (Original file will not be overwritten)
(Y/N):Y
Traceback (most recent call last):
File "\Biopython\mainscript.py", line 32, in batch_iterator
entry = next(iterator)
StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1569, in _trace
return self._trace_and_catch(frame, event, arg)
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1611, in _trace_and_catch
frame.f_back, event, marker_function_args, node
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1656, in _handle_progress_event
self._save_current_state(frame, event, args, node)
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1738, in _save_current_state
exception_info = self._export_exception_info()
File "C:\Program Files (x86)\Thonny\lib\site-packages\thonny\backend.py", line 1371, in _export_exception_info
"affected_frame_ids": exc[1]._affected_frame_ids_,
AttributeError: 'StopIteration' object has no attribute '_affected_frame_ids_'
Y a-t-il une différence entre Python 2.x et 3.x qui m'échappe ? Le problème est-il ailleurs ? Cette approche est-elle complètement erronée ? Merci d'avance !