Attempt to Load-Update-Resave Argument in a game - python

I am very new to programing and trying to learn by doing creating a text adventure game and reading Python documentation/blogs.
My issue is I'm attempting to save/load data in a text game to create some elements which carry over from game to game and are passed as arguments. Specifically with this example my goal recall, update and load an incrementing iteration each time the game is played past the intro. Specially my intention here is to import the saved march_iteration number, display it to the user as a default name suggestion, then iterate the iteration number and save the updated saved march_iteration number.
From my attempts at debugging this I seem to be updating the value and saving the updated value of 2 to the game.sav file correctly, so I believe my issues is either I'm failing to load the data properly or overwriting the saved value with the static one somehow. I've read as much documentation as I can find but from the articles I've read on saving and loading to json I cannot identify where my code is wrong.
Below is a small code snippet I wrote just to try and get the save/load working. Any insight would be greatly appreciated.
import json
def _save(dummy):
f = open("game.sav", 'w+')
json.dump(world_states, f)
f.close
def _continue(dummy):
f = open("game.sav", 'r+')
world_states = json.load(f)
f.close
world_states = {
"march_iteration" : 1
}
def _resume():
_continue("")
_resume()
print ("world_states['march_iteration']", world_states['march_iteration'])
current_iteration = world_states["march_iteration"]
def name_the_march(curent_iteration=world_states["march_iteration"]):
march_name = input("\nWhat is the name of your march? We suggest TrinMar#{}. >".format(current_iteration))
if len(march_name) == 0:
print("\nThe undifferentiated units shift nerviously, unnerved and confused, perhaps even angry.")
print("\nPlease give us a proper name executor. The march must not be nameless, that would be chaos.")
name_the_march()
else:
print("\nThank you Executor. The {} march begins its long journey.".format(march_name))
world_states['march_iteration'] = (world_states['march_iteration'] +1)
print ("world_states['march_iteration']", world_states['march_iteration'])
#Line above used only for debugging purposed
_save("")
name_the_march()

I seem to have found a solution which works for my purposes allowing me to load, update and resave. It isn't the most efficient but it works, the prints are just there to display the number being properly loaded and updated before being resaved.
Pre-requisite: This example assumes you've already created a file for this to open.
import json
#Initial data
iteration = 1
#Restore from previously saved from a file
with open('filelocation/filename.json') as f:
iteration = json.load(f)
print(iteration)
iteration = iteration + 1
print(iteration)
#save updated data
f = open("filename.json", 'w')
json.dump(iteration, f)
f.close

Related

Struggling with global dictionaries and storing data to call upon later

I am trying to read a file that has a list of tasks. The usernames are displayed on index position 0 on every line of the file. Opening the file, reading the lines and extracting that data I can do. I can get to the point of indexing the data and printing it. What I can't do is create a code to count how many times that user is present in the file. For example if a user is displayed 7 times they must have 7 tasks to complete.
The code I have so far is:
user_global = []
def disp_stats():
with open ("tasks.txt", "r", encoding='cp1252') as tu:
for lines in tu:
data_list = lines.strip("\n").split(", ")
data_list = data_list[0] #this is the data I need to count for how many tasks a user has
user_global.append(data_list)
print(user_global)
My output for this when I print is not what is as expected. What I wanted to achieve is maybe use something like Counter to count how many times a name appears in a global list. That also didn't work out too well.

i'm making face attendance system using pyqt5 that writes attendance multiple times even when the person is logged in

I'm following a Youtube tutorial of making face recognition attendance system which writes the name and time in a csv file, when i try to run it writes the name of the person many times on the attendance sheet.
i tried using logic to avoid writing the name multiple times but now it won't write the name of the person more than one time even if i start it again.
the camera is kinda slow, could it be the computer or is it the code.
def face_rec_(self, frame, encode_list_known, class_names):
def mark_attendance(ID):
"""
:taking attendance
"""
self.already_in_file = set()
date_time_string = datetime.datetime.now().strftime("%y/%m/%d, %H:%M")
with open('Attendance1.csv',"r") as f:
for line in f:
self.already_in_file.add(line.split(",")[0])
if ID and date_time_string not in self.already_in_file:
with open ("Attendance1.csv", "a") as f:
f.writelines(f'\n{ID},{date_time_string}')
I'd recommend modifying the date_time_string in the if block - it seems to me that that is the problem. The if block checks if that exact time is in the file, but time changes over time, as we know.
Lemme put it in code as well, just so my answer isn't too short!
def face_rec_(self, frame, encode_list_known, class_names):
def mark_attendance(ID):
"""
:taking attendance
"""
self.already_in_file = set()
#this at a minimum, but I believe it'll make the same mistake next hour
date_time_string = datetime.datetime.now().strftime("%y/%m/%d, %H")
#alternatively, use the one below
#date_time_string = datetime.datetime.now().strftime("%y/%m/%d")
with open('Attendance1.csv',"r") as f:
for line in f:
self.already_in_file.add(line.split(",")[0])
if ID and date_time_string not in self.already_in_file:
with open ("Attendance1.csv", "a") as f:
f.writelines(f'\n{ID},{date_time_string}')

Most efficient way to loop through a file's values and check a dictionary for any/all corresponding instances

I have a file with user's names, one per line, and I need to compare each name in the file to all values in a csv file and make note each time the user name appears in the csv file. I need to make the search as efficient as possible as the csv file is 40K lines long
My example persons.txt file:
Smith, Robert
Samson, David
Martin, Patricia
Simpson, Marge
My example locations.csv file:
GreaterLocation,LesserLocation,GroupName,DisplayName,InBook
NorthernHemisphere,UnitedStates,Pilots,"Wilbur, Andy, super pilot",Yes
WesternHemisphere,China,Pilots,"Kirby, Mabry, loves pizza",Yes
WesternHemisphere,Japan,Drivers,"Samson, David, big kahuna",Yes
NortherHemisphere,Canada,Drivers,"Randos, Jorge",Yes
SouthernHemispher,Australia,Mechanics,"Freeman, Gordon",Yes
NortherHemisphere,Mexico,Pilots,"Simpson, Marge",Yes
SouthernHemispher,New Zealand,Mechanics,"Samson, David",Yes
My Code:
import csv
def parse_files():
with open('data_file/persons.txt', 'r') as user_list:
lines = user_list.readlines()
for user_row in lines:
new_user = user_row.strip()
per = []
with open('data_file/locations.csv', newline='') as target_csv:
DictReader_loc = csv.DictReader(target_csv)
for loc_row in DictReader_loc:
if new_user.lower() in loc_row['DisplayName'].lower():
per.append(DictReader_loc.line_num)
print(DictReader_loc.line_num, loc_row['DisplayName'])
if len(per) > 0:
print("\n"+new_user, per)
print("Parse Complete")
def main():
parse_files()
main()
My code currently works. Based on the sample data in the example files, the code matches the 2 instances of "Samson, David" and 1 instance of "Simpson, Marge" in the locations.csv file. I'm hoping that someone can give me guidance on how I might transform either the persons.txt file or the locations.csv file (40K+ lines) so that the process is as efficient as it can be. I think it currently takes 10-15 minutes. I know looping isn't the most efficient, but I do need to check each name and see where it appears in the csv file.
I think #Tomalak's solution with SQLite is very useful, but if you want to keep it closer to your original code, see the version below.
Effectively, it reduces the amount of file opening/closing/reading that is going on, and hopefully will speed things up.
Since your sample is very small, I could not do any real measurements.
Going forward, you can consider using pandas for these kind of tasks - it can be very convenient working with CSVs and more optimized than the csv module.
import csv
def parse_files():
with open('persons.txt', 'r') as user_list:
# sets are faster to match against than lists
# do the lower() here to avoid repetition
user_set = set([u.strip().lower() for u in user_list.readlines()])
# open file at beginning, close after done
# you could also encapsulate the whole thing into a `with` clause if
# desired
target_csv = open("locations.csv", "r", newline='')
DictReader_loc = csv.DictReader(target_csv)
for user in user_set:
per = []
for loc_row in DictReader_loc:
if user in loc_row['DisplayName'].lower():
per.append(DictReader_loc.line_num)
print(DictReader_loc.line_num, loc_row['DisplayName'])
if len(per) > 0:
print("\n"+user, per)
print("Parse Complete")
target_csv.close()
def main():
parse_files()
main()

How to generate auto increment in a folder in python?

I am new to Python. Anyone help with how to generate auto-increment like B00001, B00002, B00003...... which can autosave the excel file name with a button in a specific folder.
I have tried with
global numXlsx
numXlsx = 1
wb.save(f'invoice/B{numXlsx}.xlsx')
numXlsx += 1
But when I click the button for few times with different data, it still keeps overwriting the B1.xlsx file. Anyone help with this :)
It sounds like the biggest problem you're having is that each button click is re-starting the execution of your python script, so using a global variable won't work since that doesn't persist across executions. In this case, I'd suggest using something like the pickle module to store and reload your counter value each time you execute your script. Using that module, your solution could look something like this:
import pickle
from pathlib import Path
# creates file if it doesn't exist
myfile = Path("save.p")
myfile.touch(exist_ok=True)
persisted = {}
with (open(myfile, "rb")) as f:
try:
persisted = pickle.load(f)
except EOFError:
print("file was empty, nothing to load")
# use get() to avoid KeyError if key doesn't exist
if persisted.get('counter') is None:
persisted['counter'] = 1
wb.save(f"invoice/B{persisted.get('counter')}.xlsx")
persisted['counter'] += 1
# save everything back into the same file to be used next execution
pickle.dump(persisted, open(myfile, "wb"))
BONUS: If you want the count to be padded with zeros in the filename, use persisted.get('counter'):05d in the curly brackets when saving the file. The 5 indicates you want the resulting value to be at least 5 characters long, so for example 2 would become 00002 and 111 would become 00111.
You can try using a global variable and incrementing it everytime.
Try with something like:
(inizialize it to 0)
global numXlsx # this is like your counter variable)
wb.save(f'folder/B{numXlsx}.xlsx')
numXlsx += 1 # Incrementing the variable so it does not overwrite the file as your code is doing
Have a nice day!

python: write input to file and save it

So, I started doing some python recently and I have always like to lift some weights as well. Therefore, I was thinking about a little program where I can put in my training progress (as some kind of python excercise).
I do something like the following as an example:
from sys import argv
file = argv[1]
target_file = open(file, 'w')
weigth = raw_input("Enter what you lifted today: ")
weigth_list = []
weigth_list.append(weigth)
file.write(weigth_list)
file.close()
Now, I know that a lot is wrong here but this is just to get across the idea I had in mind. So what I was hoping to do, was creating a file and getting a list into and store the "raw_input()" in that file. Then I want to save that file and the next time I run the script (say after the next training), I want to save another number and put that to the list. Additionally, I want to do some plotting with the data stored in the list and the file.
Now, I know I could simply do that in Excel but I would prefer to do it in python. Hopefully, someone understood what I mean.
Unsure what exactly your weight_list looks like, or whether you're planning this for one specific workout or the general case, but you'll probably want to use something like a CSV (comma-separated values) format to save the info and be able to easily plot it (for the general case of N different workout types). See below for what I mean:
$ ./record-workout saved-workouts.csv
where the record-form is
<workout type>,<number of sets>,<number of reps>,<weight>
and saved-workouts.csv is the file we'll save to
then, modifying your script ever-so-slightly:
# even though this is a small example, it's usually preferred
# to import the modules from a readability standpoint [1]
import sys
# we'll import time so we can get todays date, so you can record
# when you worked out
import time
# you'll likely want to check that the user provided arguments
if len(sys.argv) != 2:
# we'll print a nice message that will show the user
# how to use the script
print "usage: {} <workout_file>".format(sys.argv[0])
# after printing the message, we'll exit with an error-code
# because we can't do anything else!
sys.exit(1)
# `sys.argv[1]` should contain the first command line argument,
# which in this case is the name of the data file we want
# to write to (and subsequently read from when we're plotting)
# therefore, the type of `f` below is `str` (string).
#
# Note: I changed the name from `file` to `filename` because although `file`
# is not a reserved word, it's the name of a built-in type (and constructor) [2]
filename = sys.argv[1]
# in Python, it's recommended to use a `with` statement
# to safely open a file. [3]
#
# Also, note that we're using 'a' as the mode with which
# to open the file, which means `append` rather than `write`.
# `write` will overwrite the file when we call `f.write()`, but
# in this case we want to `append`.
#
# Lastly, note that `target_file` is the name of the file object,
# which is the object to which you'll be able to read or write or append.
with open(filename, 'a') as target_file:
# you'd probably want the csv-form to look like
#
# benchpress,2,5,225
#
# so for the general case, let's build this up
workout = raw_input("Enter what workout you did today: ")
num_sets = raw_input("Enter the number of sets you did today")
num_reps = raw_input("Enter the number of reps per set you did today")
weight = raw_input("Enter the weight you lifted today")
# you might also want to record the day and time you worked out [4]
todays_date = time.strftime("%Y-%m-%d %H:%M:%S")
# this says "join each element in the passed-in tuple/list
# as a string separated by a comma"
workout_entry = ','.join((workout, num_sets, num_reps, weight, todays_date))
# you don't need to save all the entries to a list,
# you can simply write the workout out to the file obj `target_file`
target_file.write(workout_entry)
# Note: I removed the `target_file.close()` because the file closes when the
# program reaches the end of the `with` statement.
The structure of saved-workouts.csv would thus be:
workout,sets,reps,weight
benchpress,2,5,225
This would also allow you to easily parse the data when you're getting ready to plot it. In this case, you'd want another script (or another function in the above script) to read the file using something like below:
import sys
# since we're reading the csv file, we'll want to use the `csv` module
# to help us parse it
import csv
if len(sys.argv) < 2:
print "usage: {} <workout_file>".format(sys.argv[0])
sys.exit(1)
filename = sys.argv[1]
# now that we're reading the file, we'll use `r`
with open(filename, 'r') as data_file:
# to use `csv`, you need to create a csv-reader object by
# passing in the `data_file` `file` object
reader = csv.reader(data_file)
# now reader contains a parsed iterable version of the file
for row in reader:
# here's where you'll want to investigate different plotting
# libraries and such, where you'll be accessing the various
# points in each line as follows:
workout_name = row[0]
num_sets = row[1]
num_reps = row[2]
weight = row[3]
workout_time = row[4]
# optionally, if your csv file contains headers (as in the example
# above), you can access fields in each row using:
#
# row['weight'] or row['workout'], etc.
Sources:
[1] https://softwareengineering.stackexchange.com/questions/187403/import-module-vs-from-module-import-function
[2] https://docs.python.org/2/library/functions.html#file
[3] http://effbot.org/zone/python-with-statement.htm
[4] How to get current time in Python

Categories

Resources