Home > other >  How to use two enumerate statements in one function in python?
How to use two enumerate statements in one function in python?

Time:11-24

I am trying to take two statements and put them into the same function. This is part of a long query to import a list of csv files (all different lengths, headers, footers, and columns) into one Excel sheet for importing into a database. I would like to set up functions that can be called to streamline the process.

Right now, if I run the following code, it works and I can use the two parameters: beginFile and endFile to determine the start and end of the data for importing.

beginning = 'eventID'
ending = 'The Line Listing is wrong'

beginFile = 0
endFile = 0

with open("testbooklet.csv") as myFile:
    for num, line in enumerate(myFile, 1):
        if beginning in line:
            beginFile = num
            
with open("testbooklet.csv") as myFile:
    for num, line in enumerate(myFile, 1):
        if ending in line:
            endFile = num
            
print(beginFile,endFile)

However; if I place this into a function, then I receive two different error messages, depending on how I write the function. For this first function, the error message is AttributeError: 'function' object has no attribute 'endFile'.

beginning = 'eventID'
ending = 'The Line Listing is wrong'

beginFile = 0
endFile = 0

# Define Function to find the first and last file lines
def fileinfo(file_name):
    global beginFile
    global endFile
    
    for num, line in enumerate(file_name, 1):
        if beginning in line:
            fileinfo.beginFile = num

# def endfileinfo(file_name):        
    for num, line in enumerate(file_name, 1):
        if ending in line:
            fileinfo.endFile = num

MyFile = open("testbooklet.csv")             
fileinfo(MyFile)
print(fileinfo.beginFile, fileinfo.endFile)

For this function, the error code is: NameError: name 'endFile' is not defined

beginning = 'eventID'
ending = 'The Line Listing is wrong'

beginFile = 0
endFile = 0

def fileinfo(file_name):
    global beginFile
    
    for num, line in enumerate(file_name, 1):
        if beginning in line:
            beginFile = num
   
    global endFile
            
    for num, line in enumerate(file_name, 1):
        if ending in line:
            endFile = num

            
MyFile = open("testbooklet.csv")
fileinfo(MyFile)
print(beginFile)
print(endFile)

This is a simplistic version of the data that I'm using for testing:

enter image description here

CodePudding user response:

Don't use global variables that get mutated by functions. Instead let the function return whatever you need, and get both informations in one sweep:

def fileinfo(file):
    beginFile = None
    endFile = None
    for num, line in enumerate(file, 1):
        if beginning in line:
            beginFile = num
        if ending in line:
            endFile = num
            break  # No need to continue
    return beginFile, endFile  # return this information to caller


myFile = open("testbooklet.csv")             
beginFile, endFile = fileinfo(myFile)
print(beginFile, endFile)

CodePudding user response:

Don't use two loops. The first one is reading all of the file, so there's nothing for the second loop to read. You could fix this with file.seek(0) to return to the beginning, but there's no need in this case -- just test both conditions in a single loop.

You also should use parameters and return values rather than global variables.

def fileinfo(file, beginning, ending):
    beginFile = 0
    endFile = 0

    for num, line in enumerate(file, 1):
        if beginning in line:
            beginFile = num
        if ending in line:
            endFile = num

    return beginFile, endFile

with open("testbooklet.csv") as MyFile:
    begin, end = fileinfo(MyFile)
  • Related