So I have a unique player ID string that is stored in a JSON file after it detects on start-up that the player is new to the game.
def checkIfPlayerIsNew():
if os.path.exists("myJson.json"):
print('file exists')
k = open('myPlayerIDs.json')
print(k.read())
#print("This is the k value: {}".format(code))
#code = json.dumps(k)
getData(k.read())
else:
print('file does not exist')
f = open('myJson.json', 'x') #creates the file if it doesn't exist already
f.close()
file = open('myPlayerIDs.json', 'w')
file.write(json.dumps(str(uuid.uuid4())))
file.close
checkIfPlayerIsNew()
Now, if it detects that the player is not new it gets the ID from the JSON File and passes it to the get data function below
def getData(idCode = "X"):
print('the id code is this: {}'.format(idCode))
outputFile = json.load(open('myJson.json'))
for majorkey, subdict in outputFile.items():
if majorkey == idCode:
for subkey, value in subdict.items():
print('{} = {}'.format(subkey, value))
#playerData[subkey] = value
else:
print("ID Does not match")
break
The problem is that when I check the id code in the get data function it prints out a blank space as if the id code has been changed to nothing (which I can't figure out why it has done that) and prints this out to the terminal:
The playerID JSON File:
You can't read() a file twice without seeking back to the start. The right thing to do here is to read the file into a variable:
if os.path.exists("myJson.json"):
print('file exists')
# Read file into a variable and use it twice
with open('myPlayerIDs.json', 'r') as k:
data = k.read()
print(data)
getData(data)
#...
Related
I have some code that stores data in a dictionary and than the dictionary is stored in a JSON file:
def store_data(user_inp):
list_of_letters = list(user_inp)
list_of_colons = []
nested_dict = {}
for letter in list_of_letters:
if letter == ':':
list_of_colons.append(letter)
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
if len(list_of_colons) == 2:
str1 = ''.join(list_of_letters)
list2 = str1.split(':')
main_key = list2[0]
nested_key = list2[1]
value = list2[2]
if main_key not in storage:
storage[main_key] = nested_dict
nested_dict[nested_key] = value
print(storage, '\n', 'successfully saved!')
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
elif main_key in storage:
if nested_key in storage[main_key]:
print('this item is already saved: \n', storage)
else:
storage[main_key][nested_key] = value
print(storage, '\n', 'successfully saved!')
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
The problem is that every time I rerun the program and enter new data, the data in the JSON file is replaced by the data entered the last time I ran the program. For example: If I want to store this string: gmail:pass:1234. What my function does is this:
creates a dictionary with the user input and stores it in the JSON file:
{'gmail': {'pass': 1234}}
As long I don't close the program, the data I enter keeps adding to the JSON object. But if I close the program, run it again, and enter new data, the data I stored before is replaced by the data I entered last.
So what I want is that every time I enter a new piece of data to the dictionary, it will add it to the object stored in the JSON file. So if I run the program again and enter this input, gmail:pass2:2343, this is how it should be stored:
{'gmail': {'pass': '1234', 'pass2': '2343'}}
And if I enter this, zoom:id:1234567, I want it to add this to the object inside the JSON file, like so:
{'gmail': {'pass': '1234', 'pass2': '2343'} 'zoom': {'id': '1234567'}}
I really don't know how to fix this, I already researched but I can't find the solution to my specific case.
Hope you understand what I mean. Thank you in advance for your help.
I think this is what you are trying to do:
def update_with_item(old, new_item):
changed = True
top_key, nested_key, value = new_item
if top_key in old:
if nested_key in old[top_key]:
changed = False
print("This item is already saved: \n", storage)
else:
old[top_key][nested_key] = value
else:
old[top_key] = {nested_key: value}
return old, changed
def main():
stored = json.load(open('myStorage.json'))
old, changed = update_with_item(stored, list2)
if changed:
jf = json.dumps(old)
with open('myStorage.json', 'w') as f:
f.write(jf)
print(storage, '\n', 'successfully saved!')
I'm also not sure how you looping over the code in main, or where the list2 variable is coming from. The main function here will need to be updated to how you are looping over creating the new values etc.
The update_with_item function should resolve the issue you are having with updating the dictionary though.
for my coding assignment I am to create a file that will read a csv file, offer different attributes to do analysis over (determined by the column values. I had this code working perfectly, but after I added my first try/except block I started getting the following error:
Traceback (most recent call last): File
"/Users/annerussell/Dropbox/Infotec 1040/module 8/csval.py", line 49,
in
row1=next(reader, 'end')[0:] ValueError: I/O operation on closed file.
Here is a link to a file you can test it with if desired. As you probably guessed this is a class assignment, and I am working on learning python for gradschool anyway so any suggestions are greatly appreciated.
import csv
print('Welcome to CSV Analytics!')
# Get file name and open the file
while True:
try:
file_name = input('Enter the name of the file you would like to process: ')
with open(file_name, "rt") as infile:
# Select the attribute to be analyzed
reader=csv.reader(infile)
headers=next(reader)[0:]
max=len(headers)
except FileNotFoundError:
print('The file you entered could not be found. Please' \
+ ' enter a valid file name, ending in .csv.')
continue
except IOError:
print('The file you selected could not be opened. Please ' \
+ 'enter a valid file name, ending in .csv.')
continue
except:
print('There was an error opening or reading your file. Please ' \
+ 'enter a valid file name, ending in .csv.')
continue
else:
print ('The attributes available to analyse are:')
for col in range(1, max):
print(col, headers[col])
while True:
try:
choice=int(input('Please select the number of the attribute you would like to analyze '))
except:
print('Please enter the numeric value for the selection you choose.')
continue
else:
# Build a dictionary with the requested data
dict1= {}
numrows=-1
row1=[]
largest_value=0
key_of_largest_value=0
while row1 != 'end':
row1=next(reader, 'end')[0:]
if row1 !='end':
numrows += 1
key=row1[0]
value=float(row1[choice])
dict1[key] = value
if value>largest_value:
largest_value=value
key_of_largest_value=key
# print('dictionary entry ( key, value)', key, value)
print('Largest ', headers[choice], ' value is ', key_of_largest_value, ' with ', largest_value)
In short: After with block ends, file is closed. You can't read from it, reader will fail.
Probably you didn't notice there is one-space indent for with, replace it with common indent so it will be more clear.
Seach for python context manager for more deep understanding.
Suggestion here is to factor out all logic from try else block to process_file function, and call it inside with statement.
with open(file_name, "rt") as infile:
# Select the attribute to be analyzed
reader=csv.reader(infile)
headers=next(reader)[0:]
max=len(headers)
process_file(reader, headers, max) # <-- like that
using with you need to move second condition to it block or
replace
with open(file_name, "rt") as infile:
with
isProcessing = True
while isProcessing:
....
infile = open(file_name, "rt")
...
#end of line
#print('Largest ',....
infile.close()
# end the loop
isProcessing = False
Write a program that inputs a JSON file (format just like
example1.json) and prints out the value of the title field.
import json
# TODO: Read your json file here and return the contents
def read_json(filename):
dt = {}
# read the file and store the contents in the variable 'dt'
with open(filename,"r") as fh:
dt = json.load(fh)
###fh = open(filename, "r")
###dt = json.load(fh)
return dt
# TODO: Pass the json file here and print the value of title field. Remove the `pass` statement
def print_title(dt):
print filename["title"]
# TODO: Input a file from the user
filename = raw_input("Enter the JSON file: ")
# The function calls are already done for you
r = read_json(filename)
print_title(r)
Hi, I'm new with Python and I'm not sure what I am doing wrong. I keep getting the following message:
enter image description here
Your'e almost there, you just confused with the parameter name.
Change this:
def print_title(dt):
print filename["title"]
To:
def print_title(dt):
print dt["title"]
Im a python noob to get that out of the way and I am writing these functions using the OOP method just a FYI. My save_roster function works correctly, it saves all of the dictionary player roster to my text file 'roster'. I confirmed this by looking in the text file making sure it is all there. Now when I go to load_roster function it only loads the first key and value and none of the rest and I cant figure out why. Any help as to how I can load the entire dictionary or what I am doing wrong would be greatly appreciated.
def save_roster(player_roster):
print("Saving data...")
file = open("roster.txt", "wt")
import csv
w = csv.writer(open("roster.txt", "w"))
for key, val in player_roster.items():
w.writerow([key, val])
print("Data saved.")
file.close()
def load_roster(player_roster):
print("Loading data...")
import csv
file = open("roster.txt", "rt")
for key, val in csv.reader(file):
player_roster[key] = eval(val)
file.close()
print("Data Loaded Successfully.")
return (player_roster)
Your return (player_roster) statement is inside of the for loop, which means it only reads the first line before returning. You need to put the statement outside the loop like so:
def load_roster(player_roster):
print("Loading data...")
import csv
file = open("roster.txt", "rt")
for key, val in csv.reader(file):
player_roster[key] = eval(val)
file.close()
print("Data Loaded Successfully.")
return (player_roster)
For a class assignment, I'm supposed to grab the contents of a file, compute the MD5 hash and store it in a separate file. Then I'm supposed to be able to check the integrity by comparing the MD5 hash. I'm relatively new to Python and JSON, so I thought I'd try to tackle those things with this assignment as opposed to going with something I already know.
Anyway, my program reads from a file, creates a hash, and stores that hash into a JSON file just fine. The problem comes in with my integrity checking. When I return the results of the computed hash of the file, it's different from what is recorded in the JSON file even though no changes have been made to the file. Below is an example of what is happening and I pasted my code as well. Thanks in advance for the help.
For example: These are the contents of my JSON file
Content: b'I made a file to test the md5\n'
digest: 1e8f4e6598be2ea2516102de54e7e48e
This is what is returned when I try to check the integrity of the exact same file (no changes made to it):
Content: b'I made a file to test the md5\n'
digest: ef8b7bf2986f59f8a51aae6b496e8954
import hashlib
import json
import os
import fnmatch
from codecs import open
#opens the file, reads/encodes it, and returns the contents (c)
def read_the_file(f_location):
with open(f_location, 'r', encoding="utf-8") as f:
c = f.read()
f.close()
return c
def scan_hash_json(directory_content):
for f in directory_content:
location = argument + "/" + f
content = read_the_file(location)
comp_hash = create_hash(content)
json_obj = {"Directory": argument, "Contents": {"filename": str(f),
"original string": str(content), "md5": str(comp_hash)}}
location = location.replace(argument, "")
location = location.replace(".txt", "")
write_to_json(location, json_obj)
#scans the file, creates the hash, and writes it to a json file
def read_the_json(f):
f_location = "recorded" + "/" + f
read_json = open(f_location, "r")
json_obj = json.load(read_json)
read_json.close()
return json_obj
#check integrity of the file
def check_integrity(d_content):
#d_content = directory content
for f in d_content:
json_obj = read_the_json(f)
text = f.replace(".json", ".txt")
result = find(text, os.getcwd())
content = read_the_file(result)
comp_hash = create_hash(content)
print("content: " + str(content))
print(result)
print(json_obj)
print()
print("Json Obj: " + json_obj['Contents']['md5'])
print("Hash: " + comp_hash)
#find the file being searched for
def find(pattern, path):
result = ""
for root, dirs, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result = os.path.join(root, name)
return result
#create a hash for the file contents being passed in
def create_hash(content):
h = hashlib.md5()
key_before = "reallyBad".encode('utf-8')
key_after = "hashKeyAlgorithm".encode('utf-8')
content = content.encode('utf-8')
h.update(key_before)
h.update(content)
h.update(key_after)
return h.hexdigest()
#write the MD5 hash to the json file
def write_to_json(arg, json_obj):
arg = arg.replace(".txt", ".json")
storage_location = "recorded/" + str(arg)
write_file = open(storage_location, "w")
json.dump(json_obj, write_file, indent=4, sort_keys=True)
write_file.close()
#variable to hold status of user (whether they are done or not)
working = 1
#while the user is not done, continue running the program
while working == 1:
print("Please input a command. For help type 'help'. To exit type 'exit'")
#grab input from user, divide it into words, and grab the command/option/argument
request = input()
request = request.split()
if len(request) == 1:
command = request[0]
elif len(request) == 2:
command = request[0]
option = request[1]
elif len(request) == 3:
command = request[0]
option = request[1]
argument = request[2]
else:
print("I'm sorry that is not a valid request.\n")
continue
#if user inputs command 'icheck'...
if command == 'icheck':
if option == '-l':
if argument == "":
print("For option -l, please input a directory name.")
continue
try:
dirContents = os.listdir(argument)
scan_hash_json(dirContents)
except OSError:
print("Directory not found. Make sure the directory name is correct or try a different directory.")
elif option == '-f':
if argument == "":
print("For option -f, please input a file name.")
continue
try:
contents = read_the_file(argument)
computedHash = create_hash(contents)
jsonObj = {"Directory": "Default", "Contents": {
"filename": str(argument), "original string": str(contents), "md5": str(computedHash)}}
write_to_json(argument, jsonObj)
except OSError:
print("File not found. Make sure the file name is correct or try a different file.")
elif option == '-t':
try:
dirContents = os.listdir("recorded")
check_integrity(dirContents)
except OSError:
print("File not found. Make sure the file name is correct or try a different file.")
elif option == '-u':
print("gonna update stuff")
elif option == '-r':
print("gonna remove stuff")
#if user inputs command 'help'...
elif command == 'help':
#display help screen
print("Integrity Checker has a few options you can use. Each option "
"must begin with the command 'icheck'. The options are as follows:")
print("\t-l <directory>: Reads the list of files in the directory and computes the md5 for each one")
print("\t-f <file>: Reads a specific file and computes its md5")
print("\t-t: Tests integrity of the files with recorded md5s")
print("\t-u <file>: Update a file that you have modified after its integrity has been checked")
print("\t-r <file>: Removes a file from the recorded md5s\n")
#if user inputs command 'exit'
elif command == 'exit':
#set working to zero and exit program loop
working = 0
#if anything other than 'icheck', 'help', and 'exit' are input...
else:
#display error message and start over
print("I'm sorry that is not a valid command.\n")
Where are you defining h, the md5 object being used in this method?
#create a hash for the file contents being passed in
def create_hash(content):
key_before = "reallyBad".encode('utf-8')
key_after = "hashKeyAlgorithm".encode('utf-8')
print("Content: " + str(content))
h.update(key_before)
h.update(content)
h.update(key_after)
print("digest: " + str(h.hexdigest()))
return h.hexdigest()
My suspicion is that you're calling create_hash twice, but using the same md5 object in both calls. That means the second time you call it, you're really hashing "reallyBad*file contents*hashkeyAlgorithmreallyBad*file contents*hashKeyAlgorithm". You should create a new md5 object inside of create_hash to avoid this.
Edit: Here is how your program runs for me after making this change:
Please input a command. For help type 'help'. To exit type 'exit'
icheck -f ok.txt Content: this is a test
digest: 1f0d0fd698dfce7ce140df0b41ec3729 Please input a command. For
help type 'help'. To exit type 'exit' icheck -t Content: this is a
test
digest: 1f0d0fd698dfce7ce140df0b41ec3729 Please input a command. For
help type 'help'. To exit type 'exit'
Edit #2:
Your scan_hash_json function also has a bug at the end of it. You're removing the .txt suffix from the file, and calling write_to_json:
def scan_hash_json(directory_content):
...
location = location.replace(".txt", "")
write_to_json(location, json_obj)
However, write_to_json is expecting the file to end in .txt:
def write_to_json(arg, json_obj):
arg = arg.replace(".txt", ".json")
If you fix that, I think it should do everything as expected...
I see 2 possible problems you are facing:
for hash computation is computing from a binary representation of a string
unless you work only with ASCII encoding, the same international character e.g. č has different representations in the UTF-8 or Unicode encoding.
To consider:
If you need UTF-8 or Unicode, normalize first your content before you save it or calculate a hash
For testing purposes compare content binary representation.
use UTF-8 only for IO operations, codecs.open does all conversion
for you
from codecs import open
with open('yourfile', 'r', encoding="utf-8") as f:
decoded_content = f.read()