I'm trying to implement a save feature into my game to save a variety of information. The save part works perfectly fine, but the load part does not work. This is my current dictionary:
player_data = {'x':x, 'y':y, 'world':mapSection, 'introcomplete':homeintro}
I am loading/saving with this:
def save_game():
with open("savegame", "wb") as f:
pickle.dump(player_data, f)
def load_game():
with open("savegame", "rb") as f:
global player_data
player_data = pickle.load(f)
And to see what mapSection is set as, I use this:
load_game()
print(player_data)
if "1_1" in player_data:
print('maploaded')
game_map_1_1()
else:
print('reset')
game_intro()
But for some reason, it always skips over the if statement to the else statement. I don't know what I am doing wrong.
I'm guessing what you really want to do is check player_data['world'] == '1_1' and not '1_1' in player_data. The second one checks if you have a key named 1_1.
This is not specific to pickle.
Related
so as i have written in title i have problem with 2 things, mainly i want to add values in to a list and dont delete already existing, but i cant figure out how to do it, for now when im writing something everything old gets deleted. My second problem is that i cant make condition to use upper letter T and lower t, can anyone help me? here is the code:
import pickle
zadania = []
a = input("Do you want to add value? T/N")
while True:
if a == 'T':
zadania.append(str(input('Write what you want to add: ')))
a = input("Do you want add something else? T/N")
elif a == 'N':
break
else:
while a not in 'TN':
print("Wrong value")
a = input("Do you want add something else? T/N")
with open('zad', 'wb') as fp:
pickle.dump(zadania, fp)
zadania = []
This always starts with an empty list. If you don't want that, then you should do something different. For example, you could check if the file you wrote before already exists. If it does, load it before getting more items.
For lower and upper case you could use if check as follows:
if a.lower()=="t":
pass
OR
if a.upper()=="T":
pass
Regarding list, your list is adding new element in existing list.
But if you are loading your list from pickle then you should first initialize zadania to pickle value and not directly [] empty. If pickle is not having any value then assign [] else pickle value.
Currently working on a school project based on a JSON dataset about a weapon list in a videogame. I've been trying to add functionality where the user can click a button that runs code filtering the dataset down to the forms containing the key-word. Below is the back end code for one of the functions, returning all forms where name = dagger
def wpn_dagger():
with open('DSweapons.json', encoding='utf-8') as outfile:
data = json.load(outfile)
wpn_list = []
for dict in data:
if dict in ['name'] == 'dagger':
wpn_list.append(data)
print(wpn_list)
return wpn_list
Whilst I do not get any errors when I run the code the only output to the terminal is an empty set of [] brackets. Any help on this issue would be much appreciated.
if dict in ['name'] == 'dagger' is wrong syntax for what you want
when written like that ['name'] is a list containing the string 'name', so dict in ['name'] is checking if dict is in that list (will be always false) and then we check if the result of that == 'dagger', i.e. the whole thing reads as if False == 'dagger'
Try this:
def wpn_dagger():
with open('DSweapons.json', encoding='utf-8') as outfile:
data = json.load(outfile)
wpn_list = []
for weapon in data:
if weapon['name'] == 'dagger':
wpn_list.append(weapon)
print(wpn_list)
return wpn_list
Indentation in python is very important. Your for loop needs to be indented so it operates inside the with context manager.
Secondly, dict is a keyword in python, so use something different if you need to name a variable.
Finally you can get an object out of your form using .get('name') on the dictionary, it's at least easier to read in my opinion.
In summary, something like this (not tested):
def wpn_dagger():
with open('DSweapons.json', encoding='utf-8') as outfile:
data = json.load(outfile)
wpn_list = []
for form in data:
if form.get('name') == 'dagger':
wpn_list.append(form)
print(wpn_list)
return wpn_list
I'm relatively new to working in Python and can't quite figure this little problem out.
I have a function that takes a .txt file input and reads each line, and based on what is on that line, it will reference a dictionary to assign a variable name. That variable is then assigned a value (also from the .txt file). I've managed to set it up to successfully do this part, but I cannot get it to return those variables as a function output.
Here is a simplified example of what I have:
The .txt file looks something like this:
File Title: 'Test_Template.env' # filename
Number of Objects: 1 # Ns
Object Size: 20 # sd
And the function is something like:
def read_env_inputs(envFilename):
env_dict = {'File Title': 'filename',
'Number of Objects': 'Ns',
'Object Size': 'sd'}
with open(envFilename) as f:
lines = f.readlines()
for line in lines:
line = line.split(':')
if line[0] in env_dict.keys():
if line[0] == 'File Title':
vars()[env_dict[line[0]]] = line[1].split('#')[0].strip()
else:
if len(line[1].split('#')[0].split(',')) == 1:
vars()[env_dict[line[0]]] = float(line[1].split('#')[0].strip())
else:
vars()[env_dict[line[0]]] = list(map(float,line[1].split('#')[0].split(',')))
return filename Ns sd
If I run this as a script (not a function), I end up having the properly named variables in my workspace and can manipulate them. However, this does not successfully define them in a way that allows them to be an output of the function.
I'm trying to avoid creating an if/elif statement for each variable. I'd like it to be able to reference the dictionary based on the key (which is working) and use the value associated with that key as the variable name.
The main problem here is that you are accessing vars() which is the dictionary containing variables that are in scope and, therefore, you cannot return this. vars() something that is very rarely used and isn't the correct solution in this case.
Assuming that the txt file doesn't contain repeating lines you can do something like this:
def read_env_inputs(envFilename):
env_dict = {"File Title": "filename", "Number of Objects": "Ns", "Object Size": "sd"}
# Result dictionary
res = {}
with open(envFilename) as f:
lines = f.readlines()
# We already read the file and don't need to stay inside the with open block
# Going back one level in indentation closes the file
for line in lines:
line = line.split(":")
if line[0] in env_dict: # No need for .keys()
res_name = env_dict[line[0]] # Name it will have in the result dictionary
if line[0] == "File Title":
# No need for vars()
res[res_name] = line[1].split("#")[0].strip()
else:
if len(line[1].split("#")[0].split(",")) == 1:
# No need for vars()
res[res_name] = float(line[1].split("#")[0].strip())
else:
# No need for vars()
res[res_name] = list(map(float, line[1].split("#")[0].split(",")))
return res
You can call the function similar to this:
env = read_env_inputs(".env")
print(env["filename"])
If you really want to you can assign the result to variables like this (it shouldn't be necessary):
filename = env["filename"]
Ns = env["Ns"]
sd = env["sd"]
Or if you want to use vars() (not best practices):
for name, value in env.items():
vars()[name] = value
Btw this code still contains some duplication. everywhere you have line[1].split("#")[0] you can substitute this for a variable (similar to what is done to res_name).
I have this python code. Can someone tell me what the conditions 'nodedef' and 'edgedef' stand for, what rule need to be satisfied that the condition is true.
I tryed to google the answer, but I didn't find anything usefull. I'm new to python so forgive me for my ignorance.
import numpy
import pandas
import networkx as nx
import unicodecsv as csv
path="comics-network.csv"
graph = nx.Graph(name="Characters in Comics")
with open(path, 'rb') as data:
reader = csv.reader(data)
for row in reader:
if 'nodedef' in row[0]:
handler = lambda row,G: G.add_node(row[0],TYPE=row[1])
elif 'edgedef' in row[0]:
handler = lambda row,G: G.add_edge(*row)
else:
handler=(row, graph)
I will try to guess, commenting line by line:
# for each row in the CSV
for row in reader:
# if the first column of the row contains the string 'nodedef'
if 'nodedef' in row[0]:
# make the name "handler" point to this function (node?)
handler = lambda row,G: G.add_node(row[0],TYPE=row[1])
# else, check if it contains the string 'edgedef'
elif 'edgedef' in row[0]:
# make the name "handler" point to this function instead (edge?)
handler = lambda row,G: G.add_edge(*row)
else:
# make the name "handler" point to this tuple (root?)
handler=(row, graph)
I presume it is doing something with "handler" afterwards.
It looks like this is the beginning of some code that constructs an in-memory representation of a graph based on a human readable representation of a graph (e.g. adjacency list).
I suspect that your CSV uses the strings 'nodedef' to state that the following data on the line refers to a node in the graph, and 'edgedef' to state that the following data refers to an edge on the graph.
I'm attempting to:
load dictionary
update/change the dictionary
save
(repeat)
Problem: I want to work with just 1 dictionary (players_scores)
but the defaultdict expression creates a completely seperate dictionary.
How do I load, update, and save to one dictionary?
Code:
from collections import defaultdict#for manipulating dict
players_scores = defaultdict(dict)
import ast #module for removing string from dict once it's called back
a = {}
open_file = open("scores", "w")
open_file.write(str(a))
open_file.close()
open_file2 = open("scores")
open_file2.readlines()
open_file2.seek(0)
i = input("Enter new player's name: ").upper()
players_scores[i]['GOLF'] = 0
players_scores[i]['MON DEAL'] = 0
print()
scores_str = open_file2.read()
players_scores = ast.literal_eval(scores_str)
open_file2.close()
print(players_scores)
You are wiping your changes; instead of writing out your file, you read it anew and the result is used to replace your players_scores dictionary. Your defaultdict worked just fine before that, even if you can't really use defaultdict here (ast.literal_eval() does not support collections.defaultdict, only standard python literal dict notation).
You can simplify your code by using the json module here:
import json
try:
with open('scores', 'r') as f:
player_scores = json.load(f)
except IOError:
# no such file, create an empty dictionary
player_scores = {}
name = input("Enter new player's name: ").upper()
# create a complete, new dictionary
players_scores[name] = {'GOLF': 0, 'MON DEAL': 0}
with open('scores', 'w') as f:
json.dump(player_scores, f)
You don't need defaultdict here at all; you are only creating new dictionary for every player name anyway.
I think one problem is that to index the data structure the way you want, something like a defaultdict(defaultdict(dict)) is what's really needed — but which unfortunately it's impossible to specify one directly like that. However, to workaround that, all you need to do is define a simple intermediary factory function to pass to the upper-level defaultdict:
from collections import defaultdict
def defaultdict_factory(*args, **kwargs):
""" Create and return a defaultdict(dict). """
return defaultdict(dict, *args, **kwargs)
Then you can use players_scores = defaultdict(defaultdict_factory) to create one.
However ast.literal_eval() won't work with one that's been converted to string representation because it's not one of the simple literal data types the function supports. Instead I would suggest you consider using Python's venerable pickle module which can handle most of Python's built-in data types as well custom classes like I'm describing. Here's an example of applying it to your code (in conjunction with the code above):
import pickle
try:
with open('scores', 'rb') as input_file:
players_scores = pickle.load(input_file)
except FileNotFoundError:
print('new scores file will be created')
players_scores = defaultdict(defaultdict_factory)
player_name = input("Enter new player's name: ").upper()
players_scores[player_name]['GOLF'] = 0
players_scores[player_name]['MON DEAL'] = 0
# below is a shorter way to do the initialization for a new player
# players_scores[player_name] = defaultdict_factory({'GOLF': 0, 'MON DEAL': 0})
# write new/updated data structure (back) to disk
with open('scores', 'wb') as output_file:
pickle.dump(players_scores, output_file)
print(players_scores)