This question already has answers here:
Using global variables in a function
(25 answers)
Closed 4 years ago.
The problem that I am running into is that 'data' variable is not being set whenever I try to read in the json object. I only get an empty set. Below I have the code and the outputs.
import json
data = []
def add(name, amt):
data.append({"ticker": name, "amount": amt})
def write():
with open('portfolio.json', 'w') as file:
json.dump(data, file)
def load():
with open('portfolio.json', 'r') as file:
data = json.load(file)
def main():
choice = input("Do you want to add vals? (y/n): ")
if choice == 'y':
add('btc', 43.2)
add('xrp', 256.5)
add('xmr', 655.3)
print(data)
write()
if choice == 'n':
load()
print(data)
main()
Output 1:
Do you want to add vals? (y/n): y
[{'ticker': 'btc', 'amount': 43.2}, {'ticker': 'xrp', 'amount': 256.5}, {'ticker': 'xmr', 'amount': 655.3}]
Press any key to continue . . .
So now the file 'portfolio.json' contains the json object with all of the data, correct? So, now when I try to read that in, this is what I get:
Output 2:
Do you want to add vals? (y/n): n
[]
Press any key to continue . . .
As you can see, the data variable is just an empty set, and it is not taking in the data. However, if I were to go inside the load function and print out the data variable, I would get my value.
You need to add a return statement in your load function and store the result in data variable before printing it.
Ex:
def load():
with open(filename, 'r') as file:
return json.load(file)
def main():
choice = input("Do you want to add vals? (y/n): ")
if choice == 'y':
add('btc', 43.2)
add('xrp', 256.5)
add('xmr', 655.3)
print(data)
write()
if choice == 'n':
data = load()
print(data)
Related
I am practicing python and doing an exercise where I have to ask for input of different information from patients of a hospital (name, last name, etc) this information has to be saved in a different json file. I managed to do it however I also have to make it so, with an input, I can remove/edit a specific patient from the dictionary (along with all of their info) while keeping the others intact.
I was thinking that maybe I could assign a number to every patient that's added, so this patient can be tracked with the number, however I'm not sure how to code that. I did however made a function to clear everything from the json file, but it has to remove/edit someone specific, not everyone.
My code so far is:
import json
def read_file(file_name):
obj_arch = open(file_name, 'rt', encoding='utf-8')
str_contenido = obj_arch.read()
res = json.loads(str_contenido)
obj_arch.close()
return res
def save_file(file_name, lista):
obj_arch = open(file_name, 'wt', encoding='utf-8')
str_content_to_save = json.dumps(lista)
print(str_content_to_save)
obj_arch.write(str_content_to_save)
obj_arch.close()
opcion = int(input("choose an option: 1 - read. 2 - save"))
if opcion == 1:
lista = read_file('prueba_json.json')
print("Full list:")
print(lista)
else:
lista = read_file('prueba_json.json')
while True:
print("--- PATIENT INFO ---")
Name = input("Input name: ")
Lastname = input("Input lastname: ")
DateB= input("Input date of birht: ")
repeat = input("Do you want to add more info?: ")
clean_file = input("Clean everything from the json file? (yes/no): ")
lista.append({
"Name": Name,
"Lastname": Lastname,
"Date of Birth": DateB
})
if repeat == 'no' or repeat == 'NO':
break
save_file('prueba_json.json',lista)
With this I was able to sabe the patients info in the json file, but how can I write another input like "Insert number of patient to remove or delete" to do that?
In order to clean the whole json file I've done it with this:
def clean_json():
with open('prueba_json.json', 'w') as arc:
arc.writelines(["[{}]"])
if clean_file == "yes" or clean_file == "YES":
clean_json()
Maybe I could adapt some of this to remove or delete someone instead of the whole file?
What I want to do is, everytime a user makes a new entry, the dictionary should be doing a new entry into my list_1.txt and then read back from it.
I got the "adding content to list_1.txt" part but I don't know how I possibly could make my dictonary read back from it.
def dictionary():
dict1 = {"name": "xyz",
"age": 25,
"hobby": "Dancing"}
if input("Do you want to update the values?[y/n]: ") == "y":
dict1["name"] = str(input("Change the name to: "))
print(dict1["name"])
dict1["age"] = int(input("Change the age to: "))
print(dict1["age"])
dict1["hobby"] = str(input("Change the hobby to: "))
print(dict1["hobby"])
elif input() != "y":
print("No valid input");
elif input() == "n":
print("Here is the current Data: " + str(dict1))
sys.exit()
print(dict1)
appendFile = open('list_1.txt','a')
appendFile.write("\n" + str(dict1))
appendFile.close()
This is the current state of the code. I already tried creating "readMe = open("list_1.txt","r").read()" and calling it inside "dict1" but as you can imagine it went horribly wrong. I'd be grateful for anykind of help and advice you could contribute.
P.S: I know my menu is buggy but I didn't put any time into it yet. This is just a little project to learn python.
It's easy to do so with the JSON module, which stores Python objects into a storage format called JSON.
Add a check in the beginning of your function to see if the file exists. If it doesn't use your default values for the dictionary, otherwise load the data from the file.
def dictionary():
if os.path.exists('list_1.txt'): # load dictionary if exists
with open('list_1.txt', 'r') as f:
dict1 = json.load(f)
else:
dict1 = { # otherwise use default values
"name": "xyz",
"age": 25,
"hobby": "Dancing"
}
When the program is done, output the data to a text file:
with open('list_1.txt', 'w') as f:
json.dump(dict1, f)
Final program:
import os
import sys
import json
def dictionary():
if os.path.exists('list_1.txt'): # load dictionary if exists
with open('list_1.txt', 'r') as f:
dict1 = json.load(f)
else:
dict1 = { # otherwise use default values
"name": "xyz",
"age": 25,
"hobby": "Dancing"
}
if input("Do you want to update the values?[y/n]: ") == "y":
dict1["name"] = str(input("Change the name to: "))
print(dict1["name"])
dict1["age"] = int(input("Change the age to: "))
print(dict1["age"])
dict1["hobby"] = str(input("Change the hobby to: "))
print(dict1["hobby"])
elif input() != "y":
print("No valid input");
elif input() == "n":
print("Here is the current Data: " + str(dict1))
sys.exit()
print(dict1)
with open('list_1.txt', 'w') as f: # save dict
json.dump(dict1, f)
use json module in python
import json
#assming folling is content of your text file
# {
# "name": "xyz",
# "age": 25,
# "hobby": "Dancing"
# }
#context manager // auto close file outside "with" clause
with open("list_1.txt",'r') as file:
#convert string '{"name": "xyz","age": 25, "hobby": "Dancing" }' into
#dictionary dict1
dict1=json.loads( file.read() )
if input("Do you want to update the values?[y/n]: ") == "y":
dict1["name"] = str(input("Change the name to: "))
print(dict1["name"])
dict1["age"] = int(input("Change the age to: "))
print(dict1["age"])
dict1["hobby"] = str(input("Change the hobby to: "))
print(dict1["hobby"])
elif input() != "y":
print("No valid input");
elif input() == "n":
print("Here is the current Data: " + str(dict1))
sys.exit()
print(dict1)
# appendFile = open('list_1.txt','a')
# appendFile.write("\n" + str(dict1))
# appendFile.close()
#use this instead
with open('list_1.txt','w') as file:
#convert dict to string
content = json.dumps(dict1)
file.write(content)
you can also use numpy
np.save('list_1.npy', dictionary)
#file extension must me .npy
Question: How do I open a file and turn it into my dictionary when I run the program?
So I created a test dictionary, saved it as .txt and .dat. Below I have entered the dictionary manually, but instead I want the program to open the file when ran, convert it to the dictionary, then continue into the functions.
(The overall objective of the program is to enter a key (productCode) to retrieve the product number, all of which works), but I want it to do it with the file, and not the manually entered data.
As always, guidance is appreciated!
file = open("test.dat", "r")
FILENAME = "test.dat"
# ------ Global Variables -------
d = {'ABCD': '0123', 'HJKL': '0987'}
user_cont = True
# ------- Functions -------
print("Product number finder.")
def get_productNum2():
global d
user_cont = True
while user_cont:
productCode = input("Enter an existing product code: ")
if productCode in d:
productNum = d[productCode]
print("Product #: " + productNum)
else:
print("Error finding product number; product code does not exist.")
user_cont = user_continue()
def user_continue():
global user_cont
prompt_user = input("Do you wish to continue? Enter y/n: ")
if prompt_user == "y":
user_cont = True
elif prompt_user == "n":
user_cont = False
return user_cont
# ------- Start Execution -------
get_productNum2()
You can (and should) write a dictionary to file in JSON format. Not only is it saved in a human-readable way, the JSON format also means the dictionary can even be loaded into many other programming languages and programs if needed!
Here is an example using the standard library package json:
import json
dict = {'ABCD': '0123', 'HJKL': '0987'}
dict_json = json.dumps(dict) #this line turns the dictionary into a JSON string
with open("my_dictionary.json", "w") as outfile:
outfile.write(dict_json)
Given a dictionary in JSON format, we can load it like this:
with open("my_dictionary.json", "r") as infile:
dict = json.load(infile)
Now you can access dict which you loaded from file as if it were the original dictionary:
>>> print(dict["ABCD"])
0123
I'm reading from a CSV file and created a function that separates the players from that file into 2 lists: experienced and fresh players.
Then, I tried to create another function that would print the length of each list. However, when I run my script and I call for the 2 functions, Python returns an error saying that the variables of the second function are not defined. Not sure what I'm doing wrong.
import csv
with open('soccer_players.csv', newline='') as csvfile:
players_reader = csv.DictReader(csvfile, delimiter=',')
players = list(players_reader)
def separate(players):
experienced = []
fresh = []
for player in players:
if player['Soccer Experience'] == 'YES':
experienced.append(player)
else:
fresh.append(player)
return experienced, fresh
def countexperience (experienced, fresh):
players_experience = len(experienced)
players_fresh = len(fresh)
print(players_experience)
print(players_fresh)
while True:
start = input("Want to start? (Y/n) ").lower()
if start == "y":
separate(players)
countexperience(experienced, fresh)
break
elif start == "n":
print("goodbye")
break
else:
print("letter not accepted! Please write 'Y' to start or 'N' to exit!\n")
Result:
countexperience(experienced, fresh)
NameError: name 'experienced' is not defined
The local variables in separate() are not added to the current scope, so you need to assign the return of separate() to variables in the current scope, e.g.:
experienced, fresh = separate(players)
Note: you can use any names you want, e.g.
e, f = separate(players)
countexperience(e, f)
You can also expand the tuple return from separate() directly in the function call to countexperience() using *, e.g.:
countexperience(*separate(players))
update:
I tried making two separate functions for saving and loading the dictionary. Works beautifully. But there still is an issue. The program will not recognize the line emails = updatedEmails
It would unpickle just fine, and those content are in their respective dictionary but I can't get it to assign those to the global 'emails' which all the other functions alter
=====================================================
import pickle
dataList = open('data.txt','wb')
global emails
emails = {}
def loading():
inFile = open('data.txt', 'rb')
updatedEmails = pickle.load(inFile)
print (updatedEmails)
inFile.close()
def saving(emails):
dataList = open('data.txt', 'wb')
pickle.dump(emails, dataList)
dataList.close()
def displayMenu():
print('\t\t\t\tMenu')
print('\t5)Display the list')
print('\t6)Quit')
def main():
choice = 0
loading()
while choice != 6:
displayMenu()
choice = int(input('Enter your choice: '))
if choice == 1:
add()
elif choice == 6:
saving(emails)
elif choice == 7:
loading()
emails = updatedEmails
main()
Your code opened the pickle file for writing first:
dataList = open('data.txt','wb')
That truncates the file to 0; by the time you then try to load pickles from that same file it is empty.
Only open the file for writing when you are actually going to write a new pickle to it, not before.