Search code examples
pythonfileloopsinsertion

I have to close a txt before iterate a second time?


I have a text file with floats in ascending order. I have to include a given float to this file preserving the order. I can`t work with lists, each float has to be in memory alone and see how it compares to the given number.

I tried open the file, create a auxiliary file and iterate the lines of the main file. first If the line is smaller than the given number, I write at the auxiliary file, then i write the number and I iterate again, this time writing the lines bigger than the number.

I did this code:

arq = open("teste.txt", "r")
aux = open(" aux.txt", "w")
for linha in arq:
    if float(linha) < float(6.00):
        aux.write(linha+"\n")

aux.write(6.00+"\n")

for linha in arq:
    if float(linha) > float(6.00):
        aux.write(linha+"\n")
arq.close()
aux.close()

But didn't work i expected, and i dont know why... Only the first iteration (lines smaller than number) worked and the inclusion of the number itself.

Then I close the file and open again after the first iteration, and this time everything was I expected.

arq = open("teste.txt", "r")
aux = open(" aux.txt", "w")
for linha in arq:
    if float(linha) < float(6.00):
        aux.write(linha+"\n")

aux.write(6.00+"\n")

arq.close()
arq = open("teste.txt", "r")

for linha in arq:
    if float(linha) > float(6.00):
        aux.write(linha+"\n")
arq.close()
aux.close()

I can`t figure out whats is the diference. Anyone can point me out? Look like I can iterate only once each time I open a txt file.


Solution

  • When you read or iterate through a file there is a pointer that tells python where you last read from, think of it like a bookmark for a physical book. Every iteration, python moves the bookmark to the end of the line it just read. Once you iterate through the file once, your bookmark was placed at the end of the file. When the code tries to iterate through again it starts from where the bookmark was last placed. In your case that means it just exits since there are no more lines to read.

    You can use arq.seek(0) to reset the 'bookmark' to the beginning:

    arq = open("teste.txt", "r")
    aux = open("aux.txt", "w")
    for linha in arq:
        if float(linha) < float(6.00):
            aux.write(linha+"\n")
    
    aux.write(6.00+"\n")
    
    arq.seek(0)
    
    for linha in arq:
        if float(linha) > float(6.00):
            aux.write(linha+"\n")
    arq.close()
    aux.close()
    

    or you can use a with statement to automatically close the file and remove the bookmark when you're done iterating:

    with open("aux.txt", "w") as aux:
        with open("teste.txt", "r") as arq:
            for linha in arq:
                if float(linha) < float(6.00):
                    aux.write(linha+"\n")
    
        aux.write(6.00+"\n")
    
        with open("teste.txt", "r") as arq:
            for linha in arq:
                if float(linha) > float(6.00):
                    aux.write(linha+"\n")
    

    or a combination of both, which will be the most efficient:

    with open("aux.txt", "w") as aux, open("teste.txt", "r") as arq:
        for linha in arq:
            if float(linha) < float(6.00):
                aux.write(linha+"\n")
    
        aux.write(6.00+"\n")
        arq.seek(0)
    
        for linha in arq:
            if float(linha) > float(6.00):
                aux.write(linha+"\n")
    

    Either way, using with is good practice as you don't run the risk of accidentally forgetting to close a file, causing all sorts of problems.