0

I'm writing a simple parser that reads a file. I'm reading the file contents into a list. I iterate through the list and send each line as an instruction to an instrument.

I'm iterating through the list like this:

for i, line in enumerate(mylines):

I check for keywords in the file and do some simple things like:

Delay N: Sleeps for N in increments one second 
Pause: Display a "Click to Continue" window

These work and of course were simple.

I'd like add a "Loop N .... EndLoop" where it will see the "Loop N" line, set a counter to N and make note of the index position of the next line (loop_start= i+ 1) of the for beginning of the loop.

Then keep iterating until it comes to the EndLoop, where I want to set i back to the noted beginning of the loop and decrement the counter.

How do can I reset the for loop index to get it to jump back to the beginning of the loop? Doesn't seem to be as simple as:

i = loop_start

or is it?

Here's my code:

    def interate(self, mylines):
    count = 0
    level = logging.INFO
    for i, line in enumerate(mylines):
       time.sleep(0.01)
       print(line)
       print(i)
       line = self.stripComments(line)
       print(line)
       count += 1
       loop_started = 0
       loop_count = 0
       if not line or re.search("^\s*$", line):
            #print('String is either empty or Blank or contain only spaces')
            pass
       else:
            first_word = line.split()[0]

            if(first_word == "Delay"):
                second_word = line.split()[1]
                if second_word.isnumeric() and int(second_word) > 0:   
                    logger.log(logging.WARNING, "DelayingI " + second_word)
                    for i in range(int(second_word), 0, -1): 
                        time.sleep(int(1))
                        logger.log(logging.WARNING, "... " + str(i))
                elif self.is_float(second_word) and float(second_word)> 0: 
                    
                    intgr, dec = divmod( float(second_word), 1)
                    print("intgr: " + str(intgr))
                    logger.log(logging.WARNING, "DelayingF " + second_word)
                    
                    for i in range(int(intgr), 0, -1): 
                        time.sleep(int(1))
                        logger.log(logging.WARNING, "... " + str(i))
                    logger.log(logging.WARNING, "and " + str(dec) + "mS")
                    time.sleep(dec)
                   
                else:    
                    logger.log(logging.ERROR, "Bad Number" + second_word)
                    print("Bad number")  
            elif(first_word == "Pause"):
                top= tk.Toplevel(self.frame)
                x = self.frame.winfo_x()
                y = self.frame.winfo_y()
                top.geometry("+%d+%d" % (x + 100, y + 200))
                top.geometry("100x100")
                top.configure(bg='#6699cc')
                top.title("Child Window")
                pause_var = tk.IntVar()
                pause_button = tk.Button(top, text='Click to Continue', command=lambda: pause_var.set(1))
                pause_button.place(relx=.5, rely=.5, anchor="c")
                pause_button.wait_variable(pause_var)
                top.destroy()
            elif(first_word == "Loop"):
                if loop_started == 0:
                    print("loop started at " + (str(i)))
                    loop_started = 1
                    second_word = line.split()[1]
                    if second_word.isnumeric() and int(second_word) > 0:
                        begin_loop = i+i
                        num_loops = second_word;
                        print("number of loops: " + str(num_loops))
            elif(first_word == "EndLoop"):
                    print("loop end at" + (str(i)))
                    loop_count = loop_count+1
                    print("loop cout:" + (str(i)))
                    if loop_count != num_loops:                           
                        i=begin_loop
                    else:
                        loop_started = 0
                        loop_count = 0
                        
                
            else:
                serialPort.write(bytes(line + '\n', encoding='utf-8'))

Thanks!

2
  • Can you post a minimal reproducible example -- just show the code relevant to the question, not all the other code. It's hard to see how all that code relates to the question. Commented Aug 10, 2022 at 23:12
  • You need a while loop to repeat a block of code. Commented Aug 10, 2022 at 23:55

1 Answer 1

1

enumerate is managing the index here and it always goes to the next one. it doesn't "add 1 to i" such that decreasing i will move it backward, it produces the next index (from an internal counter) and the for loop assigns that to i before beginning the iteration.

If you want to be able to change the index during iteration, the traditional way is to manage the index yourself and use a while loop instead of for. However, an alternative is to write your own enumerator that allows the index to be adjusted. For example:

class ListEnumerator:

    def __init__(self, seq, start=0):
        self.seq = seq
        self.index = start - 1

    def __iter__(self):
        return self

    def __next__(self):
        self.index += 1
        if self.index < len(self.seq):
            return self.index, self.seq[self.index]
        else:
            raise StopIteration

    # go back the given number of elements
    def back(self, off):
        self.index -= (off + 1)

    # skip ahead the given number of elements
    def skip(self, off):
        self.index += off

    # process the same item again on next iteration
    def again(self):
        self.index -= 1

    # process the previous item on next iteration
    def prev(self):
        self.index -= 2

    # process the given item on next iteration
    def set(self, index):
        self.index = index - 1

Usage:

items = [3, 1, 4, 1, 5, 2, 7, 2, 9]

for i, x in (e := ListEnumerator(items)):
    print(i, x)
    if x == 1:
        items[i] = 0
        e.prev()
Sign up to request clarification or add additional context in comments.

2 Comments

Okay. Thanks. Maybe I'll add another while loop inside the overall for loop.
@zonedar Added an alternative.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.