Python Forum
Cannot 'break' from a "for" loop in a right place
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Cannot 'break' from a "for" loop in a right place
#1
Hi,
I'm having a hard Cry time to 'break' from a 'for loop' in a right place.

I'm scanning a directory for the ZIP files.
And test them (from newest to the oldest) for a specific file, and if a file is in a ZIP file I want to copy that ZIP
to a different location.
The script I got so far does this:

1. Scans a directory and makes a list of ZIP files starting from the newest to the oldest.
2. Tests the Zip files from the list for a specific file (File starts with the word Debug_).
3. prints all the ZIP files with the specific file name.
I suppose to have one Zip file (latest ZIP file) from each directory but I cannot "break" the loop.

Code:

ndir_p = 'Some\\dir\\'
lst_OF_files = os.listdir(d_to_sacn)   ## Directory with ZIP files ##
full_list = [os.path.join(d_to_sacn,i) for i in lst_OF_files]
time_sorted_lst = sorted(full_list, key=os.path.getmtime)      ## ZIP files Sorted started from Newest file ##

try :        
    for ls in time_sorted_lst :
        ls=ls.strip()
        #print ("______________ ",ls)
        with ZipFile (ls, 'r') as zip_file :
            file_name_list = zip_file.namelist ()
            for file_name in file_name_list :
                if 'Debug_TIU' in file_name :               ## Looking for a specific file Name  ## 
                    print ("IN ZIP -->>  ",ls) 
                    ls_p = ls.split('\\')
                    dst = ndir_p+ls_p[-1]                   ## Creating a destination directory string ##
                    print ("ZIP Name ---------->> ", ls_p[-1])
                    print ("Destination String -->> ",dst)
                    shutil.copy(ls,dst)    
            break 
except  OSError as er  :
    print ("ERROR Opening ZIP file ",file_name)
    continue 
Thank you in advance!
Reply
#2
You could do it by using some flow_control with for/else. But I found that a little bit clumsy when I tried. So I might prefer to just use a sentinel variable and check it after each time you finish with a zip file. If you've found a match, use the variable to decide if you need to look at another one.

processed_zip_file = False
for zip_file in time_sorted_list:
    for inside_file in ZipFile(zip_file, "r").namelist():
        if "Debug_ITU" in inside_file:
            # want to copy this one.  Do what is necessary to create dst
            shutil.copy(zip_file, dst)
            processed_zip_file = True
            break
    if processed_zip_file:
        break
Reply
#3
to bowlofred:
Thank you for the snippet!
I see you are an advanced user but I'm not.
I really not that good with Python, I tried to incorporate your code into my and it did not work.
Too many errors.
"# want to copy this one. Do what is necessary to create dst"
Yes, 'dst' is a variable, it is a path to a destination directory.

It makes me upset that it is that hard to make 'break' in a right place in Python! Sick
Thank you again for trying!
Reply
#4
No, it is relatively easy to break in place of your choosing.

Can you describe in spoken language where is the right place, on which condition and where do you want to break? I believe that if you think it through then (a) you are able to solve it yourself (b) you are able to ask more generalized but more specific question (like how to break out from nested loop or something).
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#5
I got upset, you are right of course, I just do not understand the Python Loops...
Anyway, as I said, my task is to:
1. Scan remote machines (specific folders) for the ZIP files and Copy 1 (one) latest ZIP file but only if it has a file
Named "DEbug_xxx.log
2. Copy 1 (one) latest ZIP file that has "Debug_xxx.log" from each remote machine to a server.

The part of the script I need help with is the one I have already posted.
It accesses the remote machines and scans/makes a list of the ZIP files (newest to oldest)
lst_OF_files = os.listdir(d_to_sacn)   ## Directory with ZIP files ##
full_list = [os.path.join(d_to_sacn,i) for i in lst_OF_files]
time_sorted_lst = sorted(full_list, key=os.path.getmtime)      ## ZIP files Sorted started from Newest file ##


Then it finds all the ZIPs with the file "debug_xxx.log" inside the ZIPs on each remote machine and
Copies all the ZIPS to different directories on my serve (actually on my server these directories named after the remote machine names), see below :
try :        
    for ls in time_sorted_lst :
        ls=ls.strip()
        #print ("______________ ",ls)
        with ZipFile (ls, 'r') as zip_file :
            file_name_list = zip_file.namelist ()
            for file_name in file_name_list :
                if 'Debug_TIU' in file_name :               ## Looking for a specific file Name  ## 
                    print ("IN ZIP -->>  ",ls) 
                    ls_p = ls.split('\\')
                    dst = ndir_p+ls_p[-1]                   ## Creating a destination directory string ##
                    print ("ZIP Name ---------->> ", ls_p[-1])
                    print ("Destination String -->> ",dst)
                    shutil.copy(ls,dst)    
            break 
except  OSError as er  :
    print ("ERROR Opening ZIP file ",file_name)
    continue
But I need to copy only a 1 (one) ZIp file from each remote machine,
Not all as I do now.
I need to put a 'break' in the loop,

I tried to move the God damn 'break' all over the script and still cannot achieve my goal.
that is copying 1 (one) Zip file that has a 'Debug_xxx.log' inside the ZIP from each remote directory.
I hope it is clear but maybe not.
And again, I really appreciate your help!
Reply
#6
(Feb-14-2021, 05:11 AM)tester_V Wrote: "# want to copy this one. Do what is necessary to create dst"
Yes, 'dst' is a variable, it is a path to a destination directory.

I was just being lazy and didn't copy all the code you had. In other words, this would just be replaced by lines 14-18 in your original code.

(I didn't understand what the variable ls was for, so I changed it to zip_file in my code. I'm sorry if that made it more difficult to integrate. Feel free to just change that variable back to ls if that makes it easier.

If you are getting errors, tell us the errors.
Reply
#7
Thank you for your help man!
As I said before, I not really good with python, it is a very convoluted language.
I'm just trying to understand how to break out of a loop if an "if" statement is true.
"break" does not really break anything for some reason.

I made changes to my code, added lines as you suggested and it works now!
I do not understand why it started working but it does.
I really appreciate your help man!

Here is the final version of the snippet:

    processed_zip_file = False        
    for ls in time_sorted_lst :
        ls=ls.strip()
        #print ("______________ ",ls)
        try :
            with ZipFile (ls, 'r') as zip_file :
                file_name_list = zip_file.namelist ()
                for file_name in file_name_list :
                    if 'Debug_' in file_name :               ## Looking for a specific file Name  ## 
                        print ("IN ZIP -->>  ",ls)
                        ls_p = ls.split('\\')
                        dst = ndir_p+ls_p[-1]                   ## Creating a destination directory string ##
                        print ("ZIP Namae ---------->> ", ls_p[-1])
                        print ("Destination String -->> ",dst)
                        shutil.copy(ls,dst)
                        processed_zip_file = True                            
                        break 
                if processed_zip_file:
                    break     
        except  OSError as er  :
            print ("ERROR Opening ZIP file ",file_name)
            continue 
Reply
#8
break will only break out of the innermost loop.

for outer in ["A", "B", "C"]:
    for inner in ["1", "2", "3"]:
        print(outer + inner)
        if True:
            break  #exits the inner loop, but runs the next entry in the outer loop
Output:
A1 B1 C1
It looks like for your program you want to exit the outer loop. The way I suggested to do that was set a variable, then break out of the inner loop and check in the outer loop if you should exit.

all_done = False
for outer in ["A", "B", "C"]:
    for inner in ["1", "2", "3"]:
        print(outer + inner)
        if True:
            all_done = True
            break
    if all_done:  # if the inner loop set this variable, then we break the outer loop as well
        break
Output:
A1
tester_V likes this post
Reply
#9
I don't think many would agree with your opinion. Break breaks out of the loop in which it appears. Breaking out of all loops would be odd and make break difficult to use. I don't know of a language where break works differently.

Your problem is having two for loops. That is tricky in any language. I would write a function that returns True if a zip file contains a file that matches some pattern. Then your logic is much simpler. Note that none of this has been tested.
def find_file_in_zip(zip_file_name, file_pattern):
    """Return True if file matching file_pattern found in zip file"""
    try:
        with ZipFile(zip_file_name, 'r') as zip_file:
            for filename in zip_file.namelist():
                if pattern in filename:
                    return True
    except OSError:
        pass;
    return False
    
ndir_p = 'Some\\dir\\'
files = [os.path.join(d_to_sacn, i) for i in os.listdir(d_to_sacn)]

for zip_file in sorted(full_list, key=os.path.getmtime):
    zip_file = zip_file.strip()
    if find_file_in_zip(zip_file, 'Debug_TIU')
        parts = zipfile.split('\\')
        shutil.copy(zipfile, ndir_p + parts[-1])    
        break 
tester_V likes this post
Reply
#10
Thank you both!
I really appreciate your help and coaching!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  place 2 windows exactly above each other janeik 3 882 Jul-23-2023, 03:12 AM
Last Post: deanhystad
  Code won't break While loop or go back to the input? MrKnd94 2 906 Oct-26-2022, 10:10 AM
Last Post: Larz60+
  How to break out of a for loop on button press? philipbergwerf 6 1,663 Oct-06-2022, 03:12 PM
Last Post: philipbergwerf
  break out of for loop? User3000 3 1,384 May-17-2022, 10:18 AM
Last Post: User3000
  Asyncio: Queue consumer gets out of while loop without break. Where exactly and how? saavedra29 2 2,602 Feb-07-2022, 07:24 PM
Last Post: saavedra29
  tkinter control break a while loop samtal 0 2,351 Apr-29-2021, 08:26 AM
Last Post: samtal
  How to break a loop in this case? Blainexi 10 7,156 Sep-24-2020, 04:06 PM
Last Post: Blainexi
  how to break the loop? bntayfur 8 2,981 Jun-07-2020, 11:07 PM
Last Post: bntayfur
  Where should I place GPIO.cleanup() shallanq 2 2,111 Apr-11-2020, 05:02 AM
Last Post: shallanq
  break for loop Agusben 1 1,867 Apr-01-2020, 05:07 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

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