efficient counter to count incorrect input attempt from text file in python

Viewed 76

I am making a program that reads a text file that has logged values of incorrect input attempts (whether it's 'password < 6' or 'password > 10' characters). The program prints the list horizontally and makes it quite long so I wanted to make it vertical for easier read but I don't know how to. Also, for every log (password < 6 or password > 10), I was hoping to make a counter which states how many times the statements have occurred in the log file and again I don't really know how to do it.

Here's the code:

def main():
    with open("ITWorks_password_log.txt", "r") as ITWorks_password_log:
        lines = ITWorks_password_log.readlines()

    time = []
    pass_characters = []

    for l in lines:
        as_list = l.split(", ")
        time.append(as_list[0])
        pass_characters.append(as_list[1].replace("\n", ""))

    count_pw_too_small = "password < 6"
    count_pw_too_large = "password > 10"

    print(time)
    print(pass_characters)


main()

1: Sample of Text File

2021-07-22 16:24:42.843103, password < 6
2021-07-22 16:24:44.963020, password < 6
2021-07-22 16:24:49.327202, password > 10
2021-07-22 16:24:52.810838, password > 10
2021-07-22 16:24:57.057562, password > 10
2021-07-22 16:24:58.961836, password < 6
  1. Envisioned Output Two brackets with time and incorrect attempt label total count for attempts lower than 6 characters total count for attempts higher than 10 characters
1 Answers

The answer is pretty much, "just do it" for a lot of these questions, but since you did post a good bit of code, I'll suggest an alternative for your data structure. Store all the reasons in a dict, as you parse each line. I used defaultdict merely for convenience.

from collections import defaultdict

def main(inputfile):
    with open(inputfile, "r") as f:
        results = defaultdict(list)
        for line in f.readlines():
            timestamp, reason = line.strip().split(", ")
            # you should probably read the timestamp into an actual datetime object here
            results[reason].append(timestamp)
        
        for reason, timestamps in results.items():
            print ('The reason "{}" occurred {} times.'.format(reason, len(timestamps)))

main("ITWorks_password_log.txt")

The reason "password < 6" occurred 3 times.
The reason "password > 10" occurred 3 times.

Of course, if you only care about the counts, you do not need the individual timestamps. You can just store the count in a dict or defaultdict(int).

If you do want to keep all the data in a collection, then you can pass that collection to collections.Counter to get a similar result, with the downside that you'd iterate over the whole list a second time-uh. But that's not such a big deal. Here's an example with collections.Counter, but not keeping the data:

from collections import Counter

def records(filename):
    with open(filename, "r") as f:
        for line in f.readlines():
            timestamp, reason = line.split(",")
            yield reason.strip()

def main(filename):
    counter = Counter(records(filename))
    print(counter)

main("ITWorks_password_log.txt")

Counter({'password < 6': 3, 'password > 10': 3})

Related