Python Forum
Do not get how Python iterates over a file
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Do not get how Python iterates over a file
#1
Greetings!
I’m writing Python snippets here and there but I could never understand how Python iterates over a file.
It is kind of a mystery, a black box or something…
Here is an example. I’d like to merge two files.
File1:
1
2
3
File2:
1
2
3
4
5
6
7
And the snippet to merge files.
with open("C:/01/file1.txt", 'r') as f:
    with open("C:/01/file2.txt", 'r') as fe:
        for line_f in f:
            for line_fe in fe:
                if line_f == line_fe:
                    print(f"-- {line_f}")
                else:
                    print(f"++ {line_f}")
I was expecting out up as 1,2,3,4,5,6,7
But I got :
-- 1

++ 2

++ 3

Could anyone help me with this?
I even bought a Python book, it has like 3000000 pages but I still do not get it.
Why I cannot get the right printout?
Thank you.
Reply
#2
How do you expect to get 4, 5, 6, 7 in the output, when you print just lines from file 1, which end at 3?

I would suggest that you print both lines, just before the if block.

Also, note that you open BOTH files before the 2 loops. In the first iteration of the outer loop, you iterate over whole file2 (the inner loop). At that point you are at the end of file 2 and line_fe=7. There is nothing to iterate any more, so for the next 2 loops in the outer loop, the inner loop does nothing
tester_V likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
Thank you buran!
I'll try to put it in my head tomorrow morning, I hope I'll have more luck understanding it after a good sleep...
Reply
#4
well, could not get to sleep without trying it.
It prints just --1 and stops. I'm expecting the first 'for' loop will keep going but it stops.
Should print:
--1
--2
--3
with open("C:/01/file1.txt", 'r') as f:
    with open("C:/01/file2.txt", 'r') as fe:
        for line_f in f:
            #print(f"F1 >{line_f}")
            for line_fe in fe:
                #print(f"F2 >{line_fe}")
                if line_f == line_fe:
                    print(f"-- {line_fe}")
Reply
#5
Compare your code (with added DEBUG line by me):
with open("C:/01/file1.txt", 'r') as f:
    with open("C:/01/file2.txt", 'r') as fe:
        for line_f in f:
            for line_fe in fe:
                print(f'DEBUG: file1:{line_f} | file2:{line_fe}'
                if line_f == line_fe:
                    print(f"-- {line_fe}")
and


with open("C:/01/file1.txt", 'r') as f:
    for line_f in f:
        with open("C:/01/file2.txt", 'r') as fe:
            for line_fe in fe:
                print(f'DEBUG: file1:{line_f} | file2:{line_fe}'
                if line_f == line_fe:
                    print(f"-- {line_fe}")
Understand that when you reach the end of the file2 you don't get magically back to beginning just because your inner loop starts over. You are at the end of the file, you stay there unless you move back to beginning (using fe.seek(0)) or reopen the file (which will open at start again)
tester_V likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#6
thanks for coaching! I really appriciate it!
basically for each line in the first 'for' loop I reopen the second file till the second file has something to iterate. Right?
tried it, still prints:
-- 1

-- 2
and not :
--1
--2
--3

Thank you again!
Reply
#7
I guess, the last line in your file1 does NOT have new line
i.e. the line is just 3
At the same time the third line in file2 has new line, i.e. it is 3\n
So both lines are not equal.

You can strip the new line char from the lines before comparison. This will also take care of the extra blank line in your output between --1 and --2
tester_V likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
You are right! After striping the new line script prints:
it prints:
--1
--2
--3
what about printing the rest of the file1, that is :
4
5
6
7
I added an "else" block and moved it all over the place but could not print the rest of the file1.
it is really frustrating... Cry
with open("C:/01/file1.txt", 'r') as f:
    for line_f in f:
        line_f=line_f.strip()
        with open("C:/01/file2.txt", 'r') as fe:
            for line_fe in fe:
                line_fe=line_fe.strip()
                #print(f'DEBUG: file1:{line_f} | file2:{line_fe}')
                if line_f == line_fe :
                    print(f"-- {line_fe}")
                else :
                    print(f" == {line_f}")
Thank you for mentoring again!
Reply
#9
(Jan-27-2023, 07:02 PM)tester_V Wrote: what about printing the rest of the file1, that is :

well, there is no "rest of the file1" as per your first post...


(Jan-27-2023, 06:32 AM)tester_V Wrote: File1:
1
2
3

And frankly, I am not sure I understand what you try to do. And file1 being exact subset of file2 does not help either to make it more clear.
tester_V likes this post
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#10
Iterators all pretty much work the same. Once you consume all the values, there are no more values.
iterator = iter(range(5))

for i in iterator:
    print(i)

for i in iterator:
    print(i)
Output:
0 1 2 3 4
Notice the second for loop doesn't print any values because there are no values left for the iterator to provide. Files will be the same. When you open a file you have an iterator that returns lines from the file. Once you get all the lines, there are no more lines to get.

Looping is a goofy way to approach this problem. Load the contents of file2 into a set, and use the set to test if a line in file1 appears in file2.
I have two files:
test.txt
A
B
C
D

test2.txt
A
b
C
d
When I run this code:
with open("test2.txt", "r") as file:
    test2 = set(line.strip() for line in file)

with open("test.txt", "r") as file:
    for line in file:
        line = line.strip()
        print(f"=={line}" if line in test2 else f"--{line}")
This is the output:
Output:
==A --B ==C --D
tester_V likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Still do not get how Python iterates over a file tester_V 13 3,641 Aug-24-2021, 05:10 AM
Last Post: naughtyCat

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020