How to access the lines of a file read by readlines()?

Asked

Viewed 215 times

2

I’m trying to use the readlines, but it makes a mistake that I don’t understand the reason, see:

arquivo = open("cadastros.txt", "r")
loginarquivo = arquivo.readlines()[0]
senhaarquivo = arquivo.readlines()[1]
arquivo.close()

At this point when I give the print in the loginarquivo, return is the first line of the file cadastros.txt and works normally. But the second variable senhaarquivo cannot read the second line of the file cadastros.txt returning an error of list index out of range.

And the curious thing is that if I put it in line senhaarquivo = arquivo.readlines()[1] the value of zero between [] asking him to read the first line of the file that just worked with the variable loginarquivo, it will return again the list index out of range.

Finally I realized that if I do it this way:

arquivo = open("cadastros.txt", "r")
loginarquivo = open("cadastros.txt", "r").readlines()[0]
senhaarquivo = open("cadastros.txt", "r").readlines()[1]
arquivo.close()

There it works but I do not think it is the best solution between these two, besides that it does not make sense to me that it works writing open("cadastros.txt, "r")" but it doesn’t work when I enter the variable arquivo this being the same value of it and I still believe that in this second way we would have several instances of the file cadastros.txt open in memory.

Could explain why the error occurs and how to make it work the most optimized way in this case the line senhaarquivo = arquivo.readlines()[1]?

2 answers

6


The method readlines will perform the complete reading of the file, returning a list with all lines found, and with that, it is positioned at the end of the file.

When calling the method twice, you will already be at the end of the file after the first call, there will be no more lines to be read, so the method returns an empty list and at that moment you have the error, trying to access index 1 from an empty list.


To better understand, do the following test, display on the console the return value of the method readlines being called twice in a row:

arquivo = open("cadastros.txt", "r")
print(arquivo.readlines()) #Lista das linhas
print(arquivo.readlines()) #Lista vazia
arquivo.close()

To correct the error, there are many different ways, one of them would be to save the return of the method readlines in a variable and then access the indexes of that variable:

arquivo = open("cadastros.txt", "r")
linhas = arquivo.readlines()
arquivo.close()

loginarquivo = linhas[0]
senhaarquivo = linhas[1]

print(loginarquivo)
print(senhaarquivo)

Another way would be to use the method readline, see that it is in the singular, it returns only one line:

arquivo = open("cadastros.txt", "r")

loginarquivo = arquivo.readline()
senhaarquivo = arquivo.readline()

arquivo.close()

print(loginarquivo)
print(senhaarquivo)

Obs: Note also in this example that after calling the method readline, the file is positioned on the next line, not at the end of the file, so I can call the method again.

See these examples online.


Documentation:

https://docs.python.org/3.3/tutorial/inputoutput.html

https://docs.python.org/3/library/io.html

2

To another answer already explained very well the problem of using readlines several times, but lacked a small detail: both readlines when readline do not delete line breaks from the file, and the returned strings will have these characters.

For example, if the contents of the file are:

login
senha

And I read it with readlines:

with open('cadastros.txt', 'r') as arq:
    linhas = arq.readlines()
    print(linhas)

The exit will be:

['login\n', 'senha']

Note that in the login there is a \n at the end, which corresponds to the character LINE FEED (the line break). So if you use this string as login, probably won’t work, because it will have this character more.

Note also that I used with, that ensures that the file is always closed, even if an error occurs during reading (so no need to call close at the end).

In this example the password does not have the \n because in the file I used I didn’t give a ENTER after the password. But if there was another line below it, the password would also have the \n.


Anyway, one way to eliminate line breaks is to read the entire contents of the file with read and then use splitlines to "break" this content into lines (so the strings will not have the \n):

with open('cadastros.txt', 'r') as arq:
    linhas = arq.read().splitlines()
    if len(linhas) >= 2: # para garantir que há pelo menos 2 linhas
        login = linhas[0]
        senha = linhas[1]

If you want, you can exchange the last two lines for one destructuring assignment:

login, senha, *_ = linhas

Thus, both the login as to senha will not have line breaks.


The problem of readlines and read is that they carry all the contents of the file into memory. If the file is small (for example, if you "know" that "always" will have 2 lines), there is no problem. But if the file is large, it might not be worth uploading all of its content to read only two lines.

If you only want to read the first two lines and ignore the rest, you can use readline, as already suggested in the other answer, but do not forget to delete line break - an alternative is to use rstrip to eliminate her:

with open('cadastros.txt', 'r') as arq:
    login = arq.readline().rstrip('\r\n');
    senha = arq.readline().rstrip('\r\n');

I passed on to rstrip a string containing all the characters to be removed from the end. In this case, I used \n and also the \r (the CARRIAGE RETURN), because I also deal with cases where the line break is \r\n (that traditionally occurs on Windows) or simply \r (on Macos) - see more details here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.