Tian Tian - 25 days ago 5
Python Question

How to add loop to handle multiple object and multiple file in Python?

First of all, I am new to Python.

I had another question and an answer Here.

Form sloth's answer, I got the code to handle single file and single object:

import re

# so, we're looking for the object 'HeyThere'
objectname = 'HeyThere'

with open('input.txt', 'r+') as f:
line = f.readline()
pos = f.tell()
found = False
while line:

# we only want to alter the part with the
# right ObjectAlias, so we use the 'found' flag
if 'ObjectAlias ' + objectname in line:
found = True
if 'EndObject' in line:
found = False

if found and 'BeginKeyframe' in line:

# we found the Keyframe part, so we read all lines
# until EndKeyframe and count each line with 'default'
sub_line = f.readline()
frames = 0
while not 'EndKeyframe' in sub_line:
if 'default' in sub_line:
frames += 1
sub_line = f.readline()

# since we want to override the 'BeginKeyframe', we
# have to move back in the file to before this line
f.seek(pos)

# now we read the rest of the file, but we skip the
# old 'BeginKeyframe' line we want to replace
f.readline()
rest = f.read()

# we jump back to the right position again
f.seek(pos)

# and we write our new 'BeginKeyframe' line
f.write(re.sub('\d+', str(frames), line, count=1))

# and write the rest of the file
f.write(rest)
f.truncate()
# nothing to do here anymore, just quit the loop
break

# before reading a new line, we keep track
# of our current position in the file
pos = f.tell()
line = f.readline()


Due to lack of programming practice, I can't finish the code to handle multiple object and multiple file.

Say I change objectname to a list of objects and add code below "while line", the code just don't work anymore, something like this:

objectlist = ['GoodMoring', 'GoodAfternoon']
...

while line:
while objectlist:
if 'ObjectAlias ' + objectlist in line:
...


I know it is a very basic question, sorry for that, but I still have to ask this question: How to make the code handle multiple object and multiple input file?

Answer

To check for multiple objects, you can try below

for objectname in objectlist:
    if 'ObjectAlias ' + objectname in line:
        found = True

Or better one is to use any, any Return True if any element of the iterable is true

found = any('ObjectAlias ' + objectname in line for objectname in objectlist)

Full code as below

objectlist = ['GoodMoring', 'GoodAfternoon']

# can add another for loop here for list of file to process
# for ff in os.listdir():
#       with open(ff, 'r+') as f
with open('input.txt', 'r+') as f:
    line = f.readline()
    pos = f.tell()
    found = False
    while line:
        # if found already true skip checking
        found = found or any('ObjectAlias ' + objectname in line for objectname in objectlist)
        if 'EndObject' in line:
            found = False

        if found and 'BeginKeyframe' in line:
            # we found the Keyframe part, so we read all lines 
            # until EndKeyframe and count each line with 'default'
            sub_line = f.readline()
            frames = 0
            while not 'EndKeyframe' in sub_line:
                if 'default' in sub_line:
                    frames += 1
                sub_line = f.readline()

            pos2 = f.tell() # save pos to continue for next Keyframe if there is 
            # pos2 should store position of EndKeyframe now

            # since we want to override the 'BeginKeyframe', we
            # have to move back in the file to before this line
            f.seek(pos)

            # skip read rest of file coz we wanna continue next Keyframe

            # and we write our new 'BeginKeyframe' line
            f.write(re.sub('\d+', str(frames), line, count=1))

            f.seek(pos2) # restore pos because we wanna continue to process next Leyfram if there is any 

            # skip write the rest of the file
            # don't truncate and break here bcoz we wanna continue

        # before reading a new line, we keep track
        # of our current position in the file
        pos = f.tell()
        line = f.readline()