Sort Not Ordering Numbers Correctly

Hi. So I’m currently working on a logging system for Python. It’s taken forever, but I finally made a system that will create a file to log to with ease. The name of the file will be the current date, and if a file with that name already exists, it will append an underscore and a number to the end. An example would be it would log to 05-02-2023.log, then 05-02-2023_1.log on the next run; 05-02-2023_2.log on the next, and so on. But there’s a minor issue: due to how Python’s sorting method for arrays works, when it reaches 10, it can’t go any higher. This is due to 05-02-2023_10.log being placed directly after 05-02-2023_1.log in the array, and not after log nine. I’ve tried to make a custom function for it that returns the correct order of the numbers, but it has the same issue. Any ideas on how to make it so that 05-02-2023_10.log is at the end of the array?

The code for the file name generator. It’s messy and uses verbose variables, but I’m still working on it.

def setCurrentFile():
    # If there is not a logs folder, create it
    if not os.path.exists('logs'):
        os.makedirs('logs')

    # Set current date var
    now = datetime.now()
    logFileTime = now.strftime('%m-%d-%Y')

    # Create an array containing all logs in the log folder and append all logs to it
    existingLogs = []
    for x in os.listdir('logs'):
        if x.endswith('.log'):
            try:
                if 1 <= int(x[:2]) <= 12:
                    existingLogs.append(x)
            except:
                continue

    # Create another array containing all logs with the current date, as long as there's items in existingLogs[]
    logsWithCurrentDate = []
    if len(existingLogs) >= 1:
        for x in existingLogs:
            if logFileTime in x:
                logsWithCurrentDate.append(x)
        # Sort the items, making the newest log last -- THE PART THAT BREAKS
        logsWithCurrentDate.sort()
    
    # Get the latest log and parse it
    hasNoUnderscore = False
    if len(logsWithCurrentDate) >= 1:
        currentDateLog = logsWithCurrentDate[len(logsWithCurrentDate) - 1]
        # If there's an underscore in the name, the number of the log will be equal to the current log number, plus one.
        if '_' in currentDateLog:
            logNumber = f'{str(int(currentDateLog[currentDateLog.index("_") + 1:-4]) + 1)}'
        # Otherwise, it has no underscore, and the file will be named {date}_1.log.
        else:
            hasNoUnderscore = True

    # Set the log file as {date}.log if there are no logs with the current date.
    if len(logsWithCurrentDate) == 0:
        currentFile = f'{logFileTime}.log'

    # Set the log file as {date}_1.log if hasNoUnderscore is true and there is a log with the current date
    elif hasNoUnderscore and len(logsWithCurrentDate) >= 1:
        currentFile = f'{logFileTime}_1.log'
    
    # Set the log file as {date}_{number}.log is hasNoUnderscore is false and there are items in logsWithCurrentDate[]
    elif not hasNoUnderscore and len(logsWithCurrentDate) >= 1:
        currentFile = f'{logFileTime}_{logNumber}.log'
    
    # Finally, return the file name.
    return currentFile

If you need more info or more code, tell me.

That is a good idea, but could be prone to breaking(it’d be very unlikely). I’ll use that if no other fixes are found.

I did this in a function, then passed that function to sort() as the key argument. It had the same bug, for some reason.

def logFileSort(inp):
    if '_' in inp:
        return int(inp[inp.index("_") + 1:-4])
    else:
        return inp

You just need to return 0 here because you want the 05-02-2023.log to be the first element.

Also, your code was a bit complicated (using the hasNoUnderscore variable). It can be simplified like:

    logsWithCurrentDate = [log for log in existingLogs if logFileTime in log]
    if len(logsWithCurrentDate) == 1:
        return f'{logFileTime}_1.log'
    elif len(logsWithCurrentDate) > 1:
        logsWithCurrentDate.sort(key = logFileSort)
        currentDateLog = logsWithCurrentDate[-1]
        logNumber = f'{int(currentDateLog[currentDateLog.index("_") + 1:-4]) + 1}'
        return f'{logFileTime}_{logNumber}.log'
    return f'{logFileTime}.log'

This worked. Thank you so much.

And one last quick question: upon running the Log class as a function, it outputs a log to a file(using the function you helped with to select that file). Obviously it can’t run the file selection function every time something is logged because that would output every usage of Log() to a new file. So would it be better to:

  1. Run the file selection function in Main, then pass through the output to each subclass, and in those subclasses pass through the current log file as an argument in Log(), or…

  2. Run the file selection function in Main, then output that to, say, a file named current.txt in the logs folder, and upon every usage of Log it will read the file and output to the name given in that text file?

Or is there some Python function or system that I don’t know about that could be used?