1
\$\begingroup\$

I wrote a simple Python script that will calculate income for a given month and hourly wage by parsing the contents of a log file. The instructions for how to use it is in my GitHub account here. The script is used in the command line with the following command

python calculate_hours.py MY_LOG.txt MONTH YEAR HOURLY_WAGE
  • MY_LOG.txt is the text file containing the date and the number of hours worked on that day
  • MONTH and YEAR are the full (not abbreviated) month and year for which you'd like the income calculated (e.g. December 2015)
  • HOURLY_WAGE is, well, your hourly wage (e.g. 25)

The log file must be formatted in a specific way. An entry in the log should look like the following

**Date**: 21 December 2015
**Time**: 5pm - 7pm, 12-1am
**Hours**: 2, 1
**Notes**:
+ Debugged script written yesterday
+ Checked data 

The script depends on the information after **Date** and **Hours** to calculate income.

It's very simple and I was wondering if there was a way to improve it. The script looks for patterns in the log file to get the date and the hours worked.

import re
import argparse
def wage_calculator(log_txt_file, month, year, wage):
 date_pattern = "\*\*Date\*\*" # pattern identifying the date in the file
 hours_full = []
 with log_txt_file as f:
 for line in log_txt_file:
 if re.search(r"{0}".format(date_pattern), line): # go to the relevant line
 if re.search(month, line) and re.search(str(year), line): # within line, go to desired month/year
 # skips two lines to the line containing the number of hours worked
 f.next()
 hours_line = f.next()
 hours_list_str = re.findall(r'[-+]?\d*\.*\d+', hours_line) # put hours in a list
 hours_list = [float(x) for x in hours_list_str]
 hours_full += hours_list
 sum_hours_date = sum(hours_list)
 print line.rstrip()
 print "Hours logged: " + str(hours_list)
 print "Total hours for the day " + str(sum_hours_date) + "\n"
 hours_total = sum(hours_full)
 print "Total hours worked in {0} {1} is {2}".format(month, year,
 hours_total)
 print "At ${0}/hr, your total wage for {1} {2} is ${3}".format(wage, month
 , year, hours_total * wage)
def main():
 parser = argparse.ArgumentParser()
 parser.add_argument("file",
 help="Text file containing hours logged (e.g. ra_hours.txt)",
 type=argparse.FileType('r')
 )
 parser.add_argument("month",
 help="The month for which we want the income",
 type=str)
 parser.add_argument("year",
 help="Enter year",
 type=int)
 parser.add_argument("wage",
 help="Enter hourly wage",
 type=float)
 args = parser.parse_args()
 wage_calculator(args.file, args.month, args.year, args.wage)
if __name__ == '__main__':
 main()
asked Mar 7, 2016 at 4:35
\$\endgroup\$
1
  • \$\begingroup\$ Please include (at least some) instructions on how to use the code in your question. A very important part of the StackExchange idea is that questions are (predominantly) self-contained. \$\endgroup\$ Commented Mar 7, 2016 at 4:42

1 Answer 1

1
\$\begingroup\$

I think regex is a bit much for this scale of project. I decided to try rewriting your function without using regex, and I think the result is much cleaner and more Pythonic.

In addition, I replaced your hours_full list of lists with a single number that tracks the total. This greatly simplifies the code.

However, the general structure is essentially the same.

def wage_calculator(log_txt_file, month, year, wage):
 date_pattern = "**Date**: " # pattern identifying the date in the file
 hours_pattern = "**Hours**: " # pattern identifying the hours in the file
 hours_total = 0.0
 with log_txt_file as f:
 for line in log_txt_file:
 if line.startswith(date_pattern):
 if month in line and str(year) in line:
 f.next() # skip a line
 # skip the start of the line to just get a list of hours
 hours_line = f.next()[len(hours_pattern):]
 hours = sum(map(float, hours_line.split(', ')))
 hours_total += hours
 print line.rstrip()
 print "Hours logged: " + hours_line
 print "Total hours for the day " + str(hours) + "\n"
 print "Total hours worked in {0} {1} is {2}".format(month, year,
 hours_total)
 print "At ${0}/hr, your total wage for {1} {2} is ${3}".format(wage, month
 , year, hours_total * wage)

Beyond this, I would look into more error handling and data cleanup. For example, verify that the **Hours** line matches the **Time** line.

Also a .txt doesn't seem suitable for this data, maybe use a .csv?

answered Mar 7, 2016 at 21:36
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.