Edit a variable from list (Cannot use dictionary) - python

a = 10
b = 20
ls = [a, b]
How do I change the variable a to e.g. 20 using ls[0] as a parameter?
I remember there is some way to write code where you could input string and variables and it would turn into a line of code and run it.
This is how I faintly remember it, something like:
run(ls[0], "= 20")
Showing the whole code, instead of a condensed version, what I am trying to do is load and save variables from a text file. (Code is for a terminal game about making drugs.)
money = 11000
growtime = 45
growreward = 50
gramsweed = 0
growing = False
pots = 1
seeds = 0
cooktime = 90
cookreward = 20
gramsmeth = 0
cooking = False
tanks = 0
methlitres = 0
weedselling = 0
methselling = 0
currentlyselling = False
dealers = 1
dealtime = 120
dealamount = 15
stats = [money, growtime, growreward, gramsweed, growing, pots, seeds, cooktime,
cookreward, gramsmeth, cooking, tanks, methlitres, weedselling, methselling,
currentlyselling, dealers, dealtime, dealamount]
boolstats = [growing, cooking, currentlyselling]
def save():
f = open("save.txt", "w")
for stat in stats:
f.write(str(stat) + "\n")
f.close()
mainmenu()
def load():
i = 0
f = open("save.txt", "r")
for stat in stats:
print(stat)
stats[i] = f.readline(i)
i += 1
j = 0
for stat in boolstats:
if stat == "False": boolstats[j] = False
else: boolstats[j] = True
j += 1
f.close()
mainmenu()

Here's an example of how to store your game data in a dict and use the json module to easily save/load it. I'm going to start by just putting all of your variable declarations into a dict (note that I would normally use the {} syntax instead of the dict() constructor, but I'm copying and pasting your existing code and this makes it slightly easier):
stats = dict(
money = 11000,
growtime = 45,
growreward = 50,
gramsweed = 0,
growing = False,
pots = 1,
seeds = 0,
cooktime = 90,
cookreward = 20,
gramsmeth = 0,
cooking = False,
tanks = 0,
methlitres = 0,
weedselling = 0,
methselling = 0,
currentlyselling = False,
dealers = 1,
dealtime = 120,
dealamount = 15,
)
and now I can write your save and load functions in just a couple lines of code each:
import json
def save():
with open("save.txt", "w") as f:
json.dump(stats, f)
def load():
with open("save.txt") as f:
stats.update(json.load(f))
The json module takes care of reading the lines, parsing them, converting them to the right types, all of it, because it can just pull all the information it needs right out of the dictionary object. You can't get that same type of convenience and flexibility if you have a dozen different individual variables.
To suggest the ways you'd convert the other pieces of your game code to use a dict instead of individual variables I'd need to see that code, but hopefully this one example helps convince you that life can be much easier if you don't need to deal with variables one at a time!

It will not work as you desire since primitive types are passed by value. You can try:
globals()['a'] = 20 # works for global variables only, not local
or store your value in class variable, then it list will keep a reference to it.

Related

Saving a list of class objects to a JSON file that can be later read

TLDR - I want to save a few variables to a JSON file. Some of these are lists of objects belonging to custom classes. An error is raised as JSON cannot serialize them. How can I do this?
I am doing a simple text-based top trumps program where the relevant classes are as follows:
Player (sub-classes below)
Human
AI
Card
I've only been coding for around 3 months. My code for the project itself is completely functional, but I'm implementing a load option on the opening and a save option at the end of each round.
Below is my config module, it contains all the variables that are accessed by other modules, and contains everything that'd be needed for a save/load.
import json
#All variables that need to be accessed between various modules publicly
total_players = 0
players = []
dead_players = []
num_of_humans = 0
num_of_ai = 0
total_cards = 0
cards = []
def save_file():
save_name = input("Save name (You will use this to load) > ")
path = 'path_to_dir{0}.json'.format(save_name)
data = {
'total_players' : total_players,
'players' : players,
'dead_players' : dead_players,
'num_of_humans' : num_of_humans,
'num_of_ai' : num_of_ai,
'total_cards' : total_cards,
'cards' : cards
}
with open(path, 'w+') as f:
json.dump(data, f)
def load_file():
load_name = input(f"Enter the name of your save > ")
path_two = 'path_to_dir{0}.json'.format(load_name)
with open(path_two, 'r') as f:
sf = json.load(f)
total_players = str(sf['total_players'])
players = str(sf['players'])
dead_players = str(sf['dead_players'])
num_of_humans = str(sf['num_of_humans'])
num_of_ai = str(sf['num_of_ai'])
total_cards = str(sf['total_card'])
cards = str(sf['cards'])
Description of these variables:
total_players is the total amount of players as an integer
players is a list of objects that belong to either the Human or Ai class
dead_players is same as above
(self explanatory below)
num_of_humans is int
num_of_ai is int
total cards is int
cards is a list of objects of class Card
My aim is to store the state of all of these variables and be able to load them accordingly to the variables at the top. In it's current state, JSON cannot serialize the objects of my custom classes.
In load_file(), I think it should actually be:
total_cards = str(sf['total_cards'])
change your load_file with this:
json.dump(data, f,default=lambda o:o.__dict__)
This should solve your problem.

How to constantly update time variables in a Python Script?

I have an if statement below that I want to execute at exactly 11:45 am every single day. The problem is, when I run my Python script, result.tm_min and result.tm_hour are static, holding whatever time it was when I started the script in th first place. I need some way for these values to change in real-time with the clock. So when the time changes from 11:44 to 11:45, result.tm_min also changes from 44 to 45, allowing for the below if statement to execute. If I could get any help with this, that would be awesome.
I'm currently using the time and datetime libraries for this.
if result.tm_hour == 11:
if result.tm_min == 45:
post_number = random.randint(1, 5)
noun_number = random.randint(1, noun_expand_count)
verb_number = random.randint(1, verb_expand_count)
noun_file = open("nouns.txt", "r")
get_noun_line = noun_file.readlines()
new_noun = get_noun_line[noun_number].strip()
noun_file.close()
verb_file = open("verbs.txt", "r")
get_verb_line = verb_file.readlines()
new_verb = get_verb_line[verb_number].strip()
verb_file.close()
post_file = open("things_to_do.txt", "r")
get_post_line = post_file.readlines()
new_post = get_post_line[post_number].strip()
post_file.close
message = "#joerogan Hello Joe, today's top two priorities are to:", new_post, new_verb, new_noun
print(message)
#api.update_status(message)
Edit: Okay, I did a pip install for the schedule module, tried to rewrite some code, but I'm not getting any output, at all.
def post():
post_number = random.randint(1, 5)
noun_number = random.randint(1, noun_expand_count)
verb_number = random.randint(1, verb_expand_count)
noun_file = open("nouns.txt", "r")
get_noun_line = noun_file.readlines()
new_noun = get_noun_line[noun_number].strip()
noun_file.close()
verb_file = open("verbs.txt", "r")
get_verb_line = verb_file.readlines()
new_verb = get_verb_line[verb_number].strip()
verb_file.close()
post_file = open("things_to_do.txt", "r")
get_post_line = post_file.readlines()
new_post = get_post_line[post_number].strip()
post_file.close
message = "#joerogan Hello Joe, today's top two priorities are to:", new_post, new_verb, new_noun
print(message)
#api.update_status(message)
return
class MyStreamListener(tweepy.StreamListener):
def on_status(self, status):
global noun_expand_count, verb_expand_count
status = status._json['text']
schedule.every().minute.do(post)
Recalculate the current time immediately before checking:
current = datetime.now()
if current.hour == 11 and current.minute == 45:
# annoy Joe Rogan
However, as others have commented, it might be better to use a purpose-built task scheduling system such as cron.

Python help, reading and writing to a txt file

I have posted the relevant part of my code below. Before that are just load functions, which I am pretty sure have no errors.
I am recieving error
IndexError: list index out of range( "namestaj["Naziv"] = deon[1]")
Does anyone see something out of order?
#load furniture from a txt file
def ucitajNamestaj():
listaNamestaja = open("namestaj.txt", "r").readlines()
namestaj = []
for red in listaNamestaja:
namestaj.append(stringToNamestaj(red))
return namestaj
#String to Furniture, dictionary
def stringToNamestaj(red):
namestaj = {}
deon = red.strip().split("|")
namestaj["Sifra"] = deon[0]
namestaj["Naziv"] = deon[1]
namestaj["Boja"] = deon[2]
namestaj["Kolicina"] = int(deon[3])
namestaj["Cena"] = float(deon[4])
namestaj["Kategorija"] = deon[5]
namestaj["Dostupan"] = deon[6]
return namestaj
Couple of things first, try always to provide a mcve and make sure you use properly the SO code directives, otherwise your question is unreadable.
Now, probably what's happening is your file has some empty lines and you're not skipping those, try this:
def ucitajNamestaj():
listaNamestaja = open("namestaj.txt", "r").readlines()
namestaj = []
for red in listaNamestaja:
if red.strip() == "":
continue
namestaj.append(stringToNamestaj(red))
return namestaj
def stringToNamestaj(red):
namestaj = {}
deon = red.strip().split("|")
namestaj["Sifra"] = deon[0]
namestaj["Naziv"] = deon[1]
namestaj["Boja"] = deon[2]
namestaj["Kolicina"] = int(deon[3])
namestaj["Cena"] = float(deon[4])
namestaj["Kategorija"] = deon[5]
namestaj["Dostupan"] = deon[6]
return namestaj

Working with Python and pickle to save complex data in object

I am experimenting with python to do a script for a program that works with python, and I need to save an object (with custom classes and arrays inside) to a file so that I can read it afterwards (so that I don't have to remake the object everytime, which takes hours)
I was reading in many forums that the easiest way to do that is to use pickle, but I am making a mistake in some place and I don't understand where...
Now, the code would be:
First I define this class:
class Issue_class:
Title_ID = None
Publisher_ID = None
Imprint_ID = None
Volume = None
Format = None
Color = None
Original = None
Rating = None
Issue_Date_Month = None
Issue_Date_Year = None
Reprint = None
Pages = None
Issue_Title = None
Number = None
Number_str = None
Synopsis = None
Characters_ID = None
Groups_ID = None
Writer_ID = None
Inker_ID = None
Colorist_ID = None
Letterer_ID = None
CoverArtist_ID = None
Penciller_ID = None
Editor_ID = None
Alternatives_ID = None
Reprints_ID = None
Story_ID = None
Multi = None
Multistories = None
then I define a list/array for this class:
Issuesdata = []
then during a loop I fill and append these to the list:
Issuedata = Issue_class()
Issuedata.Color = "unknown"
Issuedata.Tagline = "none"
Issuedata.Synopsis = "none"
Issuedata.Format = "none"
Issuedata.Publisher_ID = "none"
Issuedata.Imprint_ID = -1
Issuedata.Title_ID = -1
Issuedata.Volume = "none"
Issuedata.Number = -1
Issuedata.Number_str = "none"
Issuedata.Issue_Title = "none"
Issuedata.Rating = -1
Issuedata.Pages = -1
Issuedata.Issue_Date_Year = 0
Issuedata.Issue_Date_Month = 0
Issuedata.Original = True
Issuedata.Reprint = False
Issuedata.Multi= True
Issuedata.Letterer_ID = []
Issuedata.Characters_ID = []
Issuedata.Story_ID = []
Issuedata.Groups_ID = []
Issuedata.Writer_ID = []
Issuedata.Penciller_ID = []
Issuedata.Alternatives_ID = []
Issuedata.Reprints_ID = []
Issuedata.Inker_ID = []
Issuedata.Colorist_ID = []
Issuedata.Editor_ID = []
Issuedata.CoverArtist_ID = []
Issuedata.Multistories = []
Then I work with the data inside the object, and when it is complete, I append it to the list:
Issuesdata.append(Issuedata)
After that I print some info inside one of the objects in the list to be sure everything is ok:
print Issuesdata[3].Title_ID
print Issuesdata[3].Publisher_ID
print Issuesdata[3].Imprint_ID
print Issuesdata[3].Volume
print Issuesdata[3].Format
etc...
And everything is ok, the printed data is perfect
Now, I try to save the list to a file with:
filehandler = open("data.dat","wb")
pickle.dump(Issuesdata,filehandler)
filehandler.close()
This create the file with info inside... but when I try to read it with:
file = open("data.dat",'rb')
Issuesdat = pickle.load(file)
file.close()
The Python console tells me "'module' object has no attribute 'Issue_class'"
The first thing I thought was that I was reading the file wrong... But then I open the saved file with notepad and inside it it was full of "wrong data", like name of files or name of classes outside the code... which makes me suspect I am dumping the data wrong in the file...
Am I using pickle wrong?
Ok, I found the problem... It seems you have to define the class of your object in the main module for pickle to see it... I had it defined in the module I was working and calling the pickle command...
Try using pandas library with simple functions like:
DataFrame.to_pickle(file-path) to save pandas Dataframe in pickle.
pandas.read_pickle(file-path) to read pickle file.
Here you can find pandas reference to_pickle read_pickle.

Python - Changing File Object within function

Sorry - My questions is how can I change a file object within a function from a different function?
I've been trying to work out this error in my first python script for too long now, Dr Google and the forums aren't helping me too much, but I'm hoping you can.
I have a looping function that generates alot of data and I would like to output it to a text file, and create a new text file after the third loop.
I have 2 functions defined, one to create the data hashes, the other to create the new files.
The new files are being created as expected (aaa.txt, baa.txt...etc) but the "hashit" function only ever writes to the first file (aaa.txt) even though the others are being created.
I have tried fo.close() fo.flush(), as well as referencing fo in the functions but can't seem to make it work. Also I've moved the fo.write from the function to the main body.
I have included a cut down version of the code that I've been using to troubleshoot this issue, the real one has several more loops increasing the string length.
Thanks in advance
import smbpasswd, hashlib
base = '''abcdefghijklmnopqrstuvwxyz '''
# base length 95
print(base)
baselen = len(base)
name = 'aaa.txt'
fo = open(name, "w")
print "Name of the file: ", fo.name
print "Closed or not : ", fo.closed
print "Opening mode : ", fo.mode
print "Softspace flag : ", fo.softspace
pw01 = 0
pw02 = 0
pw03 = 0
def hashit(passwd):
#2
# Need to install module
# sudo apt-get install python-smbpasswd
hex_dig_lm = smbpasswd.lmhash(passwd)
hex_dig_ntlm = smbpasswd.nthash(passwd)
#print '%s:%s' % smbpasswd.hash(passwd)
hash_md5 = hashlib.md5(passwd)
hex_dig_md5 = hash_md5.hexdigest()
print(passwd)
print(hex_dig_lm)
print(hex_dig_ntlm)
print(hex_dig_md5)
hashstring = passwd +","+ hex_dig_lm +","+ hex_dig_md5 + '\n'
fo.write(hashstring);
def newfile(name):
fo.flush()
fo = open(name, "a")
print("-------newfile------")
print "Name of the file: ", fo.name
print "Closed or not : ", fo.closed
print('NewFile : ' + name)
raw_input("\n\nPress the enter key to exit.")
# add 3rd digit
while (pw03 < baselen):
pwc03 = base[pw03]
name = pwc03 + 'aa.txt'
fo.close
newfile(name);
pw03 += 1
while (pw02 < baselen):
pwc02 = base[pw02]
pw02 += 1
while (pw01 < baselen):
pwc01 = base[pw01]
pw01 += 1
passwd = pwc03 + pwc02 + pwc01
hashit(passwd);
else:
pw01 = 0
else:
pw02 = 0
else:
pw03 = 0
In your newfile() function, add this line first:
global fo

Categories

Resources