Editing a CSV file in python based on an input - python

I am to create a program that collects data from a csv file, in which is stored item names and stock. I would like to display to the user how much of, for example apple, is in stock.
Item # Item name Item stock Item price
12345670 Apple 20 0.70
What would you like to buy?: 12345670
How much would you like to buy?: 10
And what I'm trying to do is edit the CSV file to display the new figure of 10 since there are 20 apples and the user purchases 10. I have tried various methods but they all give me strange errors.
My expected output would be:
Item # Item name Item stock
12345670 Apple 20
What would you like to buy?: 12345670
How much would you like to buy?: 10
You have bought 10 apple(s) for a price of £7
There are 10 apples left in stock
If the user purchases too many apples:
Item # Item name Item stock
12345670 Apple 20
What would you like to buy?: 12345670
How much would you like to buy?: 30
There are not enough apple(s) in stock to buy that amount
Would you like to buy all there is?: yes
You have bought 20 apple(s) for the price of £14
This is my code
import csv
restart = 10
list1 = []
price = 0
print("Type 'end' to end")
while restart == 10:
file1 = open("CSV File TASK 2.csv", "rt")
file2 = csv.reader(file1)
print(" ")
order = input("Type the item number of your chosen number: ")
if order == 'end':
break
for row in file2:
for field in row:
if order in field:
amount = int(input("How much of that item?: "))
row3 = int(row[3])
if amount > row3:
print("There is not enough of that item in stock")
print("Please try again")
continue
row2 = float(row[2])
row1 = str(row[1])
price = amount * row2 + price
newstock = row3 - amount
print("You have bought {} {}(s) for the price of £{:.2f}".format(amount, row1, price))
print("Your subtotal is currently at {:.2f}".format(price))
receipt = ("{} {} {} {} {}".format(row[0]+" ", row[1], str(amount), "{:10.2f}".format(float(row[2])), "{:10.2f}".format(amount * float(row[2]))))
list1.append(receipt)
print('\n'.join('{}: {}'.format(*k) for k in enumerate(list1)))
Python 3.5.2. Please and thanks in advance.

You could use this:
import csv
f = open('test.csv', 'r') # Here your csv file
r = csv.reader(f)
lines = [l for l in r]
ItemX = 0
Item = input("What would you like to buy? ")
Amount = input("How much would you like to buy? ")
for x in range(len(lines)):
if lines[x][0] == Item:
ItemX = x
else:
continue1 = True # Does nothing
f.close()
fw = open('test.csv', 'w') # Here your csv file
lines[ItemX][2] = float(lines[ItemX][2]) - float(Amount)
writer = csv.writer(fw)
writer.writerows(lines)
fw.close()

Related

Change the value of a text file Python

I am doing a POS machine which save the data in a text file. After customer buy item, the total quantity of the item in the text file will minus the quantity of the customer brought, but after I trying the code can works but the stock quantity in the text file remain unchanged. So, I found some answer from this SO question Reducing quantity in text file
, it works for them but mine can't. What gone I to do for my code work.
This is the contein of my text file named razershop.txt(id, name, price, quantity):
1 , Razer Deathadder V2, 349.00 , 100
2 , Razer Viper Ultimate, 419.00 , 105
3 , Razer Basilink Ulti, 599.00 , 35
4 , Razer Viper Mini, 139.00 , 295
5 , Raazer Deathadder X, 76.90 , 592
I used all_products to open my file:
all_products = [line.strip().split(',') for line in open('razershop.txt','r').readlines()]
This is the decrement item function code:
def decrement_item(item_id, quantity):
with open('razershop.txt', 'r') as fin:
# indexes for id and quantity
index_id = 0
index_quantity = 3
# output buffer
output = []
# Add headaer to output buffer
header = fin.readline().rstrip()
output.append(header) # header without '\n' at end of line
bfound_item = False
for line in fin:
# Check each line for item_id then upadte quantity
line = line.rstrip()
if not bfound_item:
# Only process if item_id has not been found yet
# Break line into separate fields
row = line.split()
current_id = row[index_id]
if current_id == item_id:
# Found item
# Check if sufficiente quantity
current_quantity = int(row[index_quantity])
if current_quantity >= quantity:
# Decrement quantity
current_quantity -= quantity
row[index_quantity] = str(current_quantity)
line = ' '.join(row)
bfound_item = True
else:
# Insufficient quantity for update
s = f"Sorry, available quantity is only {int(row[index_quantity])}"
raise Exception(s)
# Add line to output
output.append(line) # add copy since row changes with loop
# Update inventory file
with open('razershop.txt', 'w') as fout:
for line in output:
fout.write(line + '\n')
This is my Pos machine code which generate bill and will decrease the stock after customer buy it:
while(True):
banner()
choice = int(input("Please enter your option: "))
if choice == 1:
display_all()
elif choice == 2:
display_all()
print("Press 0 for payment")
item_lst = []
price_lst = []
quantity_lst = []
total_price = 0
prod_id = 999
while prod_id != 0:
prod_id = int(input("Enter the Product ID: "))
for item in all_products:
if int(item[0]) == prod_id:
quantity = int(input("Please enter the quantity: "))
item_lst.append(item[1])
quantity_lst.append(quantity)
price_q = float(item[2]) * quantity
price_lst.append(price_q)
total_price = total_price + price_q
decrement_item(prod_id , quantity)
order_summary(item_lst , price_lst , total_price , quantity_lst)
print(" ")
conf = input("Please confirm your order(Y/N): ")
if conf == "Y":
member = input("Do you have membership(Y/N): ")
if member == "Y":
total_price = total_price * 0.9
payment = float(input("Amount received: "))
change = payment - total_price
generate_bill(item, total_price, item_lst , price_lst , quantity_lst ,change , payment)
print(" ")
print("Thanks For shopping with Us :)")
sys.exit(0)
else:
payment = float(input("Amount received: "))
change = payment - total_price
generate_bill(item, total_price, item_lst , price_lst , quantity_lst ,change , payment)
print(" ")
print("Thanks For shopping with Us :)")
sys.exit(0)
else:
print("Continue Exploring the shop")
Output:
Upper output for customer to enter the item they want
Below part of the output which generate bill
(Sorry guys the output I can't put it in image form becuase SO not allow me so they changed my image to a link)
I had tried delete the with open('razershop.txt', 'r') as fin: and header = fin.readline().rstrip() and ( row = line.split() and change all the row variable to line fromfor line in fin: # Check each line for item_id then upadte quantity line = line.rstrip()from the decrement_item function. It end up with a infinity loop and last time I forgot what I had done with the code from the decrement_ item function the whole text in the txt file gone. I just want to know what should I do to make this work?

How to create a shopping report using information from a text file

like this
Shopping report
Name1
Thing1 number1 cost1
Thing11 number11 cost11
the amount to be paid
Name2
Thing2 number2 cost2
Thing22 number22 cost22
the amount to be paid
text file
Petrov pen 10 151000
Borzov paper 20 20000
Butar case-boks 5 5000
Semerik pen2 500 250000
Petrov pen(oil) 100 10000
Borzov paper 40 40000
Butar book 5 15000
Semerik hat 500 250000
You would do it like this:
path = "C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\Stack overflow\\textfile.txt"
newpath = "C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\Stack overflow\\textfileout.txt"
text = open(path, "r")
textinfo = text.readlines()
dictofinfo = {}
for line in textinfo:
line = line.strip()
lineaslist = line.split(" ")
name = lineaslist[0]
if not(name in dictofinfo.keys()):
dictofinfo[lineaslist[0]] = [lineaslist[1:]]
else:
dictofinfo[lineaslist[0]].append(lineaslist[1:])
text.close()
out = open(newpath, "w")
for entry in dictofinfo:
totaltobepayed = 0
out.write(entry + "\n")
for seperateentry in dictofinfo[entry]:
totaltobepayed += int(seperateentry[2])
out.write(" ".join(seperateentry) + "\n")
out.write(str(totaltobepayed) + "\n")
out.close()
Replace the path variable with the path to your text file.

Parse text for matching key then grab first set of matching table name rows

Trying to do some reconciliations with some large old flat text files(that are honestly messes). Issue I am have is that I find my matching key, I am trying to grab the first set consecutive of rows with a matching table names and ignoring the rest. How would I read what I need and not the rest? Playing around with breaks but the logic is escaping me.
Example: If I was looking for a PK of 101 and table name of drink, from the below list I want to print
drink 25
drink 26
FlatTextFile.txt
pk_tbl 23 100
food 0 0
drink 0 0
dessert 0 0
pk_tbl 101
food 0
drink 25
drink 26
dessert 0
drink 27
drink 28
drink 29
pk_tbl 102
food 0
drink 0
drink 0
drink 0
dessert 0
psuedo code for the example of where I am at essentially
pk_flag = 0
for row in d:
if (row[0]= 'drink') and (pk_flag =='1'):
print(row)
if (row[0]= 'pk_tbl')and (row[2] =='101'):
pk_flag = 1;
elif (row[0]= 'pk_tbl')and (row[2] !='101'):
pk_flag = 0;
A little confusing haha, any help is appreciated.
Thanks!
def get_table_data(file_path = 'FlatTextFile.txt', table_keyword = 'pk_tbl', table_num = '101', data_keyword = 'drink'):
output_ls = []
with open(file_path, 'r') as fh:
table = False
data = False
for line in fh.readlines():
if not len(line.strip()): # Ignoring blank lines
continue
row = line.split()
if not table: # Searching for table keyword and number
if row[0] == table_keyword and row[1] == table_num:
table = True
else:
if row[0] == table_keyword: # I'm already at next table
break
if not data: # Searching for data keyword
if row[0] == data_keyword:
data = True
output_ls.append(line)
else: # Searching for more consecutive data keywords
if row[0] == data_keyword:
output_ls.append(line)
else:
break
return output_ls
Assuming that the patter in the file FlatTextFile.txt is stored as:
table name
food # (none or one or more)
drink # (none or one or more)
desert # (none or one or more)
(food, drink, desert pattern can repeat for a table)
(blank line)
table name (next table name)
(food, drink, desert pattern in any order)
You want to pick the records with drink immediately after you find table pk_tbl 101. The name of the table can be pk_tbl + any string or no string + 101
With the above assumptions, here's the code to pick the specific drinks from table 101.
with open ('FlatTextFile.txt', 'r') as f:
table = False
output = []
line_count = 0
for line in f:
line = line.rstrip()
x = line.split()
if {'pk_tbl','101'} <= set(x): #checks if 'pk_tbl' and '101' are in x
table = True
continue
if table and 'drink' in x: #finds values with drinks
line_count +=1
output.append(line)
continue
if line_count > 0: break #we are past drink in table pk_tbl; stop processing
print (output)
The output of this will be:
['drink 25', 'drink 26']

Python sorting error

When I try to sort my list in python I get the following error:
Traceback (most recent call last):
File "C:/Users/natep/OneDrive/Documents/I.T/Level 2/programing/Shop_list.py", line 81, in <module>
products.sort(key = lambda x:x[3], reverse=True)
Name Measurement Price Unit Price
File "C:/Users/natep/OneDrive/Documents/I.T/Level 2/programing/Shop_list.py", line 81, in <lambda>
products.sort(key = lambda x:x[3], reverse=True)
Chips Drink
IndexError: list index out of range
50 2.0
5.0 3.0
2.5 1.0
Chips Drink
50 2.0
5.0 3.0
2.5 1.0
Process finished with exit code 1
Below is the code I am using. I would like to know how I can sort my list that contains lists. Would also like to know why my data is being printed twice and how to format the printing output better so that it corresponds to the correct column. (without importing downloads)
Any help would be greatly appreciated.
unit_price = price / measurement
unit.append(unit_price)
products.append(name_sum)
products.append(mes_sum)
products.append(money_sum)
products.append(unit)
row_entry.append(products)
average = "The average product price is ${}".format(mean(money_sum))
highest = "The most expensive item is ${}".format(max(money_sum))
low = "The cheapest item is ${}".format(min(money_sum))
print()
print("Name\t\tMeasurement\t\tPrice\t\tUnit Price" )
for item in products:
print("")
for data in item:
print(data, "\t", end='')
products.sort(key = lambda x:x[3], reverse=True)
I have added all my code below:
# Shopping list
from statistics import mean
from operator import itemgetter
def limit_check(type, question, low, high):
valid = False
error = "please enter values between {} and or equal to {}".format(low,
high)
while not valid:
try:
response = type(input(question))
if low < response <= high:
valid = True
return response
else:
print(error)
except ValueError:
print(error)
products = []
mes_sum = []
money_sum = []
name_sum = []
unit = []
row_entry = []
money = float(input("please enter your budget: $"))
get_data = True
while get_data == True:
name = input("please enter product name: ")
if name.lower() == "xxx":
break
else:
name_sum.append(name)
price = limit_check(float,"How much does the item cost", 0, money)
money_sum.append(price)
measurement = limit_check(int,"Please enter unit of measurement Push 1
for kg, push 2 for g, push 3 for L, push 4 for mL",0,4)
if measurement == int("1"):
kg = limit_check(float, "Enter Kg: ", 0, 10)
mes_sum.append(kg)
elif measurement == int("2"):
grams = limit_check(int, "Enter Grams: ", 0, 999)
mes_sum.append(grams)
elif measurement == int("3"):
litres = limit_check(float, "Enter Litres: ", 0, 30)
mes_sum.append(litres)
elif measurement == int("4"):
mL = limit_check(int, "Enter mL: ", 0, 999)
mes_sum.append(mL)
unit_price = price / measurement
unit.append(unit_price)
for i in range(len(name_sum)):
products.append([name_sum[i], mes_sum[i], money_sum[i], unit[i]])
average = "The average product price is ${}".format(mean(money_sum))
highest = "The most expensive item is ${}".format(max(money_sum))
low = "The cheapest item is ${}".format(min(money_sum))
print()
print("Name\t\tMeasurement\t\tPrice\t\tUnit Price" )
for item in products:
print("")
for data in item:
print(data, "\t", end='')
products.sort(key = lambda x:x[1], reverse=True)
Currently prints like this:
Name Measurement Price Unit Price
looooool 1.0 10.0 10.0
looooool 1.0 10.0 10.0
lol 1.0 1.0 1.0
Process finished with exit code 0
Your code seems to expect that the lists in the products list each have 4 elements (for Name, Measurement, Price, and Unit Price), but in reality your data only have two elements in each list (for Chips and Drink).
Then when you try to sort products, which contains lists of length 2, you access the 4th value in the lambda function. This triggers the error: there are only two values, not 4.
It looks like you have transposed the data that you wanted to end up in products. Instead of:
products.append(name_sum)
products.append(mes_sum)
products.append(money_sum)
products.append(unit)
do:
for i in range(len(name_sum)):
products.append([name_sum[i], mes_sum[i], money_sum[i], unit[i]])
Or more compactly:
products.extend(list(map(list, zip(*[name_sum, mes_sum, money_sum, unit]))))

Looping over a text file list with python

EDIT: Have updated post for better clarity, no answers have yet to help!
Alright, so my assignment is to take a text file, that would have 4 entries per line, those being firstName, lastName, hours, payRate. I'm to do some calculations and throw all this information in a formatted table in python. Now, I've got the code to enter the data into the table, but it only works for the first entry in the text file, and I can't quite make it loop. I honestly feel like an idiot, and that this is just a simple fix.
My output is supposed to look like this:
http://i.imgur.com/bIOBqye.png
Could really use some pointers on making this loop through and print the data from each line of the text file. Here's how my current code looks:
heading1 = "{0:15s}{1:15s}{2:10s}{3:15s}{4:20s}{5:15s}".format("First Name", "Last Name", "Hours", "Payrate", "Overtime Hours", "Gross Pay")
heading2= "=============================================================================================================="
print(heading1)
print(heading2)
if os.path.isfile(fileQuestion) == True:
file = open('emps', 'r')
data = file.readlines()
for tmp in data:
data2= [word.rstrip("\n") for word in data]
first = data2[0].split()
lastName = first[0]
firstName = first[1]
first[2]=(int(first[2]))
first[3]=(int(first[3]))
initialHours = first[2]
payRate = first[3]
if initialHours > 40:
overHours = initialHours - 40
regHours = 40
regPay = payRate * regHours
otPay = overHours * (payRate * 1.5)
grossPay = regPay + otPay
else:
regHours = first[2]
grossPay = initialHours * payRate
overHours = 0
heading3= "{0:15s}{1:15s}{2:2d}{3:10d}{4:14d} {5:24.2f}".format(firstName, lastName, regHours, payRate, overHours, grossPay)
heading4= "{0:15s}{1:21.2f}".format("Total Gross Pay", grossPay)
heading5= "{0:15s}{1:19.2f}".format("Average Gross Pay", grossPay)
heading6= "{0:15s}{1:16d}".format("Total Overtime Hours", 33)
spaceHeading = " "
print(heading3)
print(spaceHeading)
print(heading4)
print(heading5)
print(heading6)
Please let me know if I haven't done this correctly or anything, first time here. Thanks.
I found the duplicate, and think some people treat rude ;/ Just not focus on pragmatic problems of programmers but on good rules of Stack in bad way :(
Here is my complete answer for your problem:
1)
First of all, you must remember that ident is used against code block's brackets known from another landuages.
I reformatted your code remember that all of lines should have extra spaces at the beginning when you pase it here ;)
2) like it was said:
first = word.split()
fix "not changing" of lines in loop.
3) Total overtime hours have hardcoded number:
heading6= "{0:15s}{1:16d}".format("Total Overtime Hours", overHours)
Also, overHours(All?) should be not "zeroed" in 'else' block in loop. You must initialize it before loop.
I change some other places i.e. some hardcoded ints, maybe it not ideal and in your style, but you have code with my fixes below...
Best, if you use GitHub or Bitbucket or another repo accesible by web, because you help to contribute if you want it, and also - yourself, to find all the changes which was done. And then, just ask here to help in extremely unknown problems. In the begging of learning it is always hard to find out, but later - you could achieve more!
Here is code after my changes:
from os.path import isfile as isFileExsist
import sys
filePath = input("What is the name of your file?: ")
while isFileExsist(filePath) == False:
pos = ['y', 'Y', 'yes', 'Yes']
neg = ['n', 'N', 'no', 'No']
answer = input("File not found! Do you want to start again? (y-yes/n-no)")
if answer in neg:
exit("Bye!")
elif answer in pos:
filePath = input("What is the name of your file?: ")
continue
else:
print("Not sure what is the answer. Try again!")
continue
file = open(filePath, 'r')
data = file.readlines()
print("{0:15s}{1:15s}{2:10s}{3:15s}{4:20s}{5:15s}".format("First Name", "Last Name", "Hours", "Payrate", "Overtime Hours", "Gross Pay"))
print("==============================================================================================================")
overHoursAll = 0
grossPayAll = 0
count = 0
for line in data:
words = line.split()
lastName = words[0]
firstName = words[1]
initialHours=(int(words[2]))
payRate =(int(words[3]))
if initialHours > 40:
regHours = 40
overHours = initialHours - 40
regPay = payRate * regHours
otPay = overHours * (payRate * 1.5)
grossPay = regPay + otPay
else:
regHours = initialHours
overHours = 0
grossPay = initialHours * payRate
grossPayAll += grossPay
overHoursAll += overHours
# heading3
print("{0:15s}{1:15s}{2:2d}{3:10d}{4:14d}{5:24.2f}".format(firstName, lastName, regHours, payRate, overHours, grossPay))
# space heading
print(" ")
# overall stats
print("{0:15s}{1:21.2f}".format("Total Gross Pay", grossPayAll))
print("{0:15s}{1:19.2f}".format("Average Gross Pay", grossPayAll / len(data)))
print("{0:15s}{1:16d}".format("Total Overtime Hours", overHoursAll))
Best regards, I am sorry for my English.
Well, I think, you probably want data2 = [word.rstrip("\n") for word in tmp], but without seeing sample input and desired output it's hard to tell.
Also,
first[2]=(int(first[2]))
first[3]=(int(first[3]))
initialHours = first[2]
payRate = first[3]
Could be:
initialHours = int(first[2])
payRate = int(first[3])
But you'd also need to change other references to first[2]
Finally, I'd change
if os.path.isfile(fileQuestion) == True:
file = open('emps', 'r')
data = file.readlines()
for tmp in data:
to:
if os.path.isfile(fileQuestion) == True:
with open('emps', 'r') as myfile:
for tmp in myfile:
This ensures that the file gets closed properly (your code doesn't close it), and iterates directly through the file, rather than using readlines() which needlessly reads the entire file to memory before doing enything else. Note that file is a python builtin, so a bad choice of variable name.
You are using these lines:
data = file.readlines()
for tmp in data:
which already splits your data into lines, and iterates through them. That means that this line [data2= [word.rstrip("\n") for word in data]] is setting data2 to be the first line EVERY TIME, which renders the original for loop useless.
Try instead:
tmp = tmp.split()
which will split each line as you iterate, you can now call tmp as a list, like you called first except it will reflect the values for each line.
You could also change your original for loop to:
for tmp in file:
since file objects in python are generators that yield each line (this saves you some memory space)
try these changes:
totothrs = 0
totgross = 0.0
employees = 0
for tmp in data:
employees += 1
fname, lname, rate, hrs = tm.split()
hrs = int(hrs)
rate = float(rate)
othrs = 0
if hrs > 40:
othrs = hrs - 40
hrs = hrs - othrs
totothrs += othrs
gross = rate * hrs + (1.5*rate)*othrs
totgross += gross
heading3= "{0:15s}{1:15s}{2:2d}{3:10d}{4:14d} {5:24.2f}".format(firstName, lastName, hrs, rate, othrs, gross)
print heading3
spaceHeading = " "
heading4= "{0:15s}{1:21.2f}".format("Total Gross Pay", totgross)
heading5= "{0:15s}{1:19.2f}".format("Average Gross Pay", (totgross/employees)
heading6= "{0:15s}{1:16d}".format("Total Overtime Hours", totothrs)
print heading4
print heading5
print heading6
Note: you dontneed to define the "headingN"'s you can just print them
import os.path
import sys
#fileQuestion = input("What is the name of your file?: ")
fileQuestion = "Testfile.txt"
heading1 = "{0:15s}{1:15s}{2:10s}{3:15s}{4:20s}{5:15s}".format("First Name", "Last Name", "Hours", "Payrate", "Overtime Hours", "Gross Pay")
heading2= "=============================================================================================================="
print(heading1)
print(heading2)
if os.path.isfile(fileQuestion) == True:
file_handle = open(fileQuestion, 'r')
#file = open('emps', 'r')
#data = file.readlines() I would't go for readline here
#file_handle2 = open('outupt.txt')
total_gross_pay = 0
number_of_employees = 0
average_gross_pay = 0
total_overtime = 0
standard_working_hours = 40
for i in file_handle:
data = i.rstrip().lstrip().split()
#print (data)
first_name, last_name, hours, payrate = data
hours = int(hours)
payrate = int(payrate)
basic_pay = hours * payrate
if(hours > standard_working_hours):
overtime = hours - standard_working_hours
overtime_premium = overtime * payrate
gross_pay = overtime_premium + basic_pay
else:
overtime = 0
gross_pay = basic_pay
total_overtime += overtime
total_gross_pay += gross_pay
number_of_employees += 1
print("{0:15s}{1:15s}{2:10s}{3:15s}{4:20s}{5:15s}".format(first_name, last_name, str(hours), str(payrate), str(overtime), str(gross_pay)))
print('\n')
print("Total Gross Pay: ",total_gross_pay)
print("Average Gross Pay: ",total_gross_pay/number_of_employees)
print("Total overtime: ",total_overtime)

Categories

Resources