I am wondering how I can save whatever I added to a list when I close a python file. For example, in this "my contact" program that I wrote below, if I add information about 'Jane Doe', what could I do so that next time I open up the same file, Jane Doe still exists.
def main():
myBook = Book([{"name": 'John Doe', "phone": '123-456-7890', "address": '1000 Constitution Ave'}])
class Book:
def __init__(self, peoples):
self.peoples = peoples
self.main_menu()
def main_menu(self):
print('Main Menu')
print('1. Display Contact Names')
print('2. Search For Contacts')
print('3. Edit Contact')
print('4. New Contact')
print('5. Remove Contact')
print('6. Exit')
self.selection = input('Enter a # form the menu: ')
if (self.selection == "1"):
self.display_names()
if (self.selection == "2"):
self.search()
if (self.selection == "3"):
self.edit()
if (self.selection == "4"):
self.new()
if (self.selection == "5"):
self.delete()
if (self.selection == "6"):
self.end()
def display_names(self):
for people in self.peoples:
print("Name: " + people["name"])
self.main_menu()
def search(self):
searchname = input('What is the name of your contact: ')
for index in range(len(self.peoples)):
if (self.peoples[index]["name"] == searchname):
print("Name: " + self.peoples[index]["name"])
print("Address: " + self.peoples[index]["address"])
print("Phone: " + self.peoples[index]["phone"])
self.main_menu()
def edit(self):
searchname = input('What is the name of the contact that you want to edit: ')
for index in range(len(self.peoples)):
if (self.peoples[index]["name"] == searchname):
self.peoples.pop(index)
name = input('What is your name: ')
address = input('What is your address: ')
phone = input('What is your phone number: ')
self.peoples.append({"name": name, "phone": phone, "address": address})
self.main_menu()
def new(self):
name = input('What is your name: ')
address = input('What is your address: ')
phone = input('What is your phone number: ')
self.peoples.append({"name": name, "phone": phone, "address": address})
self.main_menu()
def delete(self):
searchname = input('What is the name of the contact that you want to delete: ')
for index in reversed(range(len(self.peoples))):
if (self.peoples[index]["name"] == searchname):
self.peoples.pop(index)
print(searchname, 'has been removed')
self.main_menu()
def end(self):
print('Thank you for using the contact book, have a nice day')
print('Copyright Carson147 2019©, All Rights Reserved')
main()
Use a module from the Data Persistence section of the standard library, or save it as json, or as a csv file.
You just convert your list to array inside in function .
np.save('path/to/save', np.array(your_list))
to load :
arr=np.load(''path/to/save.npy').tolist()
I hope it will be helpful
There are innumerable kinds of serialization options, but a time-tested favorite is JSON. JavaScript Object Notation looks like:
[
"this",
"is",
"a",
"list",
"of",
"strings",
"with",
"a",
{
"dictionary": "of",
"values": 4,
"an": "example"
},
"can strings be single-quoted?",
false,
"can objects nest?",
{
"I": {
"Think": {
"They": "can"
}
}
}
]
JSON is widely used, and the Python stdlib has a method of converting objects to and from JSON in the json package.
>>> import json
>>> data = ['a', 'list', 'full', 'of', 'entries']
>>> json.dumps(data) # dumps will dump to string
["a", "list", "full", "of", "entries"]
You can then save your Book data to json before the program shuts down, and read from json after it starts up.
# at the top
import json
from pathlib import Path
# at the bottom of your program:
if __name__ == '__main__':
persistence = Path('book.json')
if persistence.exists():
with persistence.open() as f:
data = json.load(f)
else:
data = [{"name": 'John Doe', "phone": '123-456-7890', "address": '1000 Constitution Ave'}]
book = Book(data)
with persistence.open('w') as f:
json.dump(f, indent=4)
There is no way you can do that without any external modules, such as numpy or pickle. Using pickle, you can do this: (I am assuming you want to save the myBook variable)
import pickle
pickle.dump(myBook, open("foo.bar", "wb")) #where foo is name of file and bar is extension
#also wb is saving type, you can find documentation online
To load:
pickle.load(myBook, open("foo.bar", "rb"))
EDIT:
I was wrong in my first statement. There is a way to save without importing a module. Here is how:
myBook.save(foo.bar) #foo is file name and bar is extention
To load:
myBook=open(foo.bar)
As evinced by the many other answers, there are many ways to do this, but I thought it was helpful to have a example.
By changing the top of your file as so, you can use the shelve module.
There are a variety of other things you can fix in your code if you are curious, you could try https://codereview.stackexchange.com/ if you want more feedback.
import shelve
def main():
default = [
{'name': 'John Doe', 'phone': '123-456-7890',
'address': '1000 Constitution Ave'}
]
with Book('foo', default=default) as myBook:
myBook.main_menu()
class Book:
def __init__(self, filename, default=None):
if default is None:
default = []
self._db = shelve.open(filename)
self.people = self._db.setdefault('people', default)
def __enter__(self):
return self
def __exit__(self):
self._db['people'] = self.people
self._db.close()
Related
I have a base.json file that I would like to split into smaller ones containing only filtered data by my python script where I am using json module. At the moment I can filter the data but I don't know how to save them to the appropriate files like: user, computer, group, printer, etc.
I would like to achieve the effect that after checking the base file, the data was properly saved to smaller files:
users --> users.json
computers --> computers.json
groups --> groups.json
etc.
First, I would like to know how to save data to separate files, then I know that what is repeated can be closed in the function def save_to_string(data_to_save)
My base json looks like this:
{
"entries": [
{
"attributes": {
all attributes from ldap like cn, sn, objectClass, etc
},
"dn": "CN=group1,OU=Groups,OU=UNIVERSUM,DC=universum,DC=local"
},
{
"attributes": {
all attributes from ldap like cn, sn, objectClass, etc
},
"dn": "CN=cmptr-01,OU=Computers,OU=UNIVERSUM,DC=universum,DC=local"
},
{
"attributes": {
all attributes from ldap like cn, sn, objectClass, etc
},
"dn": "CN=John Doe,OU=Users,OU=UNIVERSUM,DC=universum,DC=local"
}
]
}
and my code looks:
# --- reading encoded accounts
encoded_retrieved_accounts = root_path + data_dir + encoded_accounts_file_name
with open(encoded_retrieved_accounts, 'r', encoding="UTF-8") as file:
data = json.load(file)
retrieved_accounts = data['entries']
def save_to_json(data_to_save, fname):
with open(f"./{fname}.json", 'w', encoding="UTF-8") as file:
return json.dump(data_to_save, file, ensure_ascii=False, indent=4, sort_keys=True)
for account in retrieved_accounts:
attributes = account['attributes']
objectCategory = attributes['objectCategory']
if str(objectCategory[3:-46]) == 'Person':
u_data = account
save_to_json(u_data, 'Person')
elif str(objectCategory[3:-46]) == 'Computer':
c_data = account
save_to_json(c_data, 'Computer')
elif str(objectCategory[3:-46]) == 'Organizational-Unit':
ou_data = account
save_to_json(ou_data, 'Organizational-Unit')
elif str(objectCategory[3:-46]) == 'Group':
g_data = account
save_to_json(g_data, 'Group')
elif str(objectCategory[3:-46]) == 'Print-Queue':
pq_data = account
save_to_json(pq_data, 'Print-Queue')
elif str(objectCategory[3:-46]) == 'MSMQ-Configuration':
msmq_data = account
save_to_json(msmq_data, 'MSMQ-Configuration')
else:
unknow_data = account
save_to_json(unknow_data, 'to-clarify')
but this saves only the last found account in the base file, for example users are 'n', groups are 'm', printers are 'i' and hosts are 'j'
I changed the code and now everything works fine
import os
import json
from dotenv import load_dotenv
# --- loading .env file
load_dotenv('.env')
# ------ variables
root_path = os.environ.get('ROOT_PATH')
data_dir = os.environ.get('DATA_DIR')
tmp_dir = os.environ.get('TMP_DIR')
encoded_accounts_file_name = os.environ.get('ENCODED_ACCOUNTS_FILE_NAME')
print(" - .env loaded")
# --- reading encoded accounts
encoded_retrieved_accounts = root_path + data_dir + tmp_dir + encoded_accounts_file_name
with open(encoded_retrieved_accounts, 'r', encoding="UTF-8") as file:
data = json.load(file)
retrieved_accounts = data['entries']
def save_to_json(data_to_save, fname):
with open(f"./{fname}.json", 'a', encoding="UTF-8") as file:
return json.dump(data_to_save, file, ensure_ascii=False, indent=4, sort_keys=True)
for account in retrieved_accounts:
attributes = account['attributes']
objectCategory = attributes['objectCategory']
if str(objectCategory[3:-46]) == 'Person':
u_data = account
save_to_json(u_data, 'Person')
elif str(objectCategory[3:-46]) == 'Computer':
c_data = account
save_to_json(c_data, 'Computer')
elif str(objectCategory[3:-46]) == 'Organizational-Unit':
ou_data = account
save_to_json(ou_data, 'Organizational-Unit')
elif str(objectCategory[3:-46]) == 'Group':
g_data = account
save_to_json(g_data, 'Group')
elif str(objectCategory[3:-46]) == 'Print-Queue':
pq_data = account
save_to_json(pq_data, 'Print-Queue')
elif str(objectCategory[3:-46]) == 'MSMQ-Configuration':
msmq_data = account
save_to_json(msmq_data, 'MSMQ-Configuration')
else:
unknow_data = account
save_to_json(unknow_data, 'to-clarify')
I am working on a project for a python class, where we have to create a vin number look up tool. This code below works so far for country and year made. However I am having an issue with how I am indexing the user input.
Sometimes a country is the first two characters, and other times the country code is only the first character. I do not how to get around this problem, I tried using an if else kind of method while iterating through the dictionary, but it did not work.
class vinfo():
def __init__(self):
""" Get user input """
vin = input("Enter Vin: ")
""" Stupidity check """
unaccepted_chars = [
"-","/",".",","," ","?",
"^","$","*","(",")","[",
"]","{","}","#","!","_",
"+","'","=","|","#","<",
">","`","~","&"
]
for char in vin:
if char in unaccepted_chars:
vin = vin.replace(char, "")
else:
print("", end = "")
""" Length check and index """
if len(vin) == 17:
self.country_filt1 = vin[0]
self.country_filt2 = vin[0:2]
self.engine_filt = vin[7]
self.year_filt = vin[9]
self.manufact_filt = vin[1:3]
self.manufact_filt1 = vin[1:4]
else:
print("You must've entered something really stupid.\n(must be 17 characters, letters are uppercase)")
""" Vin Code Data """
# each manufacturer seems to have multiple vins for different car styles
# and for different countries
manufact_codes = {
"1G1":"Chevy",
"":"",
}
year_codes = {
"M":"2021","L":"2020","K":"2019",
"J":"2018","H":"2017","G":"2016",
"F":"2015","E":"2014","D":"2013",
"C":"2012","B":"2011","A":"2010",
"9":"2009","8":"2008","7":"2007",
"6":"2006","5":"2005","4":"2004",
"3":"2003","2":"2002","1":"2001",
"Y":"2000","X":"1999","W":"1998",
"V":"1997","T":"1996","S":"1995",
"R":"1994","P":"1993","N":"1992",
"M":"1991","L":"1990","K":"1989",
"J":"1988","H":"1987","G":"1986",
"F":"1985","E":"1984","D":"1983",
"C":"1982","B":"1981","A":"1980"
}
country_codes = {
"1": "USA",
"4": "USA",
"5": "USA",
"7F": "USA",
"3X": "Mexico",
"37": "Mexico",
"3A": "Canada",
"3W": "Canada",
"W": "Germany",
"SA": "United Kingdom",
"SM": "United Kingdom",
"J": "Japan",
"KL": "Korea",
"KR": "Korea"
}
engine_codes = {
}
""" Define the vehicles attributes using the find() function below """
self.year = self.find(self.year_filt, year_codes)[0]
# self.country = self.find(self.country_filt, country_codes)[0]
# self.manufact = self.find(self.manufact_filt, manufact_codes)
self.engine = self.find(self.engine_filt, engine_codes)
""" Find country (different lengths of country codes) """
for key, value in country_codes.items():
if key == self.country_filt1:
country = value
elif key == self.country_filt2:
country = value
else:
country = "Unsupported code"
""" Same for manufacturer """
for key, value in manufact_codes.items():
if key == self.manufact_filt:
manufact = value
elif key == self.manufact_filt1:
manufact = value
else:
manufact = "Unsupported code"
self.info = print(f"Year: {self.year}\nManufacturer: {manufact}\nCountry: {country}\nEngine: {self.engine}")
""" search through the dictionaries """
def find(self, filt, dict_of_codes):
try:
info = [value for key, value in dict_of_codes.items() if key == filt]
except:
info = "Unsupported"
if len(info) > 1:
info += " (Could be any of these)"
return info
So, I wanted to answer this question for those who could not answer this question.
I wanted to help, so here is my answer since it was a little hard for me.
If you can think of anything better, let everyone know.
zyDE 9.15.1: Nested dictionaries example: Music library.
The following example demonstrates a program that uses 3 levels of nested dictionaries to create a simple music library.
The following program uses nested dictionaries to store a small music library. Extend the program such that a user can add artists, albums, and songs to the library. First, add a command that adds an artist name to the music dictionary. Then add commands for adding albums and songs. Take care to check that an artist exists in the dictionary before adding an album, and that an album exists before adding a song.
Answer:
music = {
'Pink Floyd': {
'The Dark Side of the Moon': {
'songs': [ 'Speak to Me', 'Breathe', 'On the Run', 'Money'],
'year': 1973,
'platinum': True
},
'The Wall': {
'songs': [ 'Another Brick in the Wall', 'Mother', 'Hey you'],
'year': 1979,
'platinum': True
}
},
'Justin Bieber': {
'My World':{
'songs': ['One Time', 'Bigger', 'Love Me'],
'year': 2010,
'platinum': True
}
}
}
prompt = ("1. Enter artist information\n"
"2. Exit\n")
command = ''
while command != '2':
command = input(prompt).lower()
if command == '1':
artist = input('Artist: ')
if artist in music.keys():
print('That artist already exists. Please try again.')
artist = input('Artist: ')
album = input('Album: ')
for albums in music.values():
if album in albums:
print('That album already exists. Please try again')
album = input('Album: ')
songs = input('Song: ').split()
music[artist] = {album: {'songs': songs}}
else:
break
print(music)
Maybe you can try this way:
prompt = ("1. Enter artist information\n"
"2. Exit\n")
command = ''
while command != '2':
command = input(prompt).lower()
if command == '1':
artist = input('Artist: ')
album = input('Album: ')
songs = input('Song: ').split()
if artist in music.keys():
print(music[artist].keys())
if album in music[artist].keys():
music[artist][album]["songs"] += songs
else:
music[artist].update({album: {}})
music[artist][album].update({"songs": songs})
else:
music.update({artist: {}})
music[artist].update({album: {}})
music[artist][album].update({"songs": songs})
print('\n', music)
I am trying to generate a pandas dataset comprising person data. I am employing Python's Faker library. Is there a way to generate a valid email address using the first name and last name?
import pandas as pd
import numpy as np
import os
import random
from faker import Faker
def faker_categorical(num=1, seed=None):
np.random.seed(seed)
fake.seed_instance(seed)
output = []
for x in range(num):
gender = np.random.choice(["M", "F"], p=[0.5, 0.5])
output.append(
{
"First name": fake.first_name_male() if gender=="M" else
fake.first_name_female(),
"Last name": fake.last_name(),
"E-mail": fake.ascii_email(),
})
return output
You can use Faker's domain_name method and string formatting alongside the already generated values:
first_name = fake.first_name_male() if gender =="M" else fake.first_name_female()
last_name = fake.last_name()
output.append(
{
"First name": first_name,
"Last Name": last_name,
"E-mail": f"{first_name}.{last_name}#{fake.domain_name()}"
}
)
On a more complete approach, you could add factoryboy to the mix:
from factory import DictFactory, LazyAttribute
from factory.fuzzy import FuzzyChoice
from factory import Faker
class PersonDataFactory(DictFactory):
first = LazyAttribute(lambda obj: fake.first_name_male() if obj._gender == "M" else fake.first_name_female())
last = Faker("last_name")
email = LazyAttribute(lambda obj: f"{obj.first}.{obj.last}#{fake.domain_name()}")
_gender = FuzzyChoice(("M", "F"))
class Meta:
exclude = ("_gender",)
rename = {"first": "First Name", "last": "Last Name", "email": "E-mail"}
PersonDataFactory()
which will result in something like:
{'First Name': 'Albert',
'Last Name': 'Martinez',
'E-mail': 'Albert.Martinez#wheeler.com'}
I'll show an alternative to the accepted answer if you need to build more complex data. This solution relies on the use of data provider that are part of the Faker library. You define a new Provider and then you add to your instance of Faker(). You can then call this generator where ever you need.
from faker.providers import BaseProvider
class CustomProvider(BaseProvider):
__provider__ = "personalia"
def personalia(self):
gender = self.random_element(["F", "M"])
first_name = self.generator.first_name_male() if gender == "M" else self.generator.first_name_female()
last_name = self.generator.last_name()
email_address = f"{first_name.lower()}.{last_name.lower()}#{self.generator.domain_name()}"
return {
"First name": first_name,
"Last Name": last_name,
"E-mail": email_address
}
fake = Faker()
fake.add_provider(CustomProvider)
personalia = fake.personalia()
print(personalia)
The output should look like this:
{
'First name': 'Olivia',
'Last Name': 'Cook',
'E-mail': 'olivia.cook#sloan.com'
}
Of course this is just an simple example based on the code you have provided. ;)
I have this JSON file.
{
"reviewers":[
{
"user":{
"name":"keyname",
"emailAddress":"John#email",
"id":3821,
"displayName":"John Doe",
"active":true,
"slug":"jslug",
"type":"NORMAL",
"link":{
"url":"/users/John",
"rel":"self"
},
},
"role":"REVIEWER",
"approved":true
},
{
"user":{
"name":"keyname2",
"emailAddress":"Harry#email",
"id":6306,
"displayName":"Harry Smith",
"active":true,
"slug":"slug2",
"link":{
"type":"NORMAL",
"url":"/users/Harry",
"rel":"self"
},
},
"role":"REVIEWER",
"approved":false
}
],
}
Initially, I was using a snippet of code that would go through and grab the full names of the reviewers.
def get_reviewers(json):
reviewers = ""
for key in json["reviewers"]:
reviewers += key["user"]["displayName"] + ", "
reviewers = reviewers[:-2]
return reviewers
which would return "John Doe, Harry Smith". However, now I'm trying to get it so that the script will return a (A) next to the name of the user if their tag equals true "approved"=true.
So for example the code above would get the names, then see that John's approved tag is true and Harry's is false, then return "John Doe(A), Harry Smith". I'm just not sure where to even begin to do this. Can anyone point me in the right direction?
This is what I've been trying so far but obviously it isn't working as I'd like it to.
def get_reviewers(stash_json):
reviewers = ""
for key in stash_json["reviewers"]:
if stash_json["reviewers"][0]["approved"] == true:
reviewers += key["user"]["displayName"] + "(A)" + ", "
else:
reviewers += key["user"]["displayName"] + ", "
reviewers = reviewers[:-2]
return reviewers
which outputs Jason Healy(A), Joan Reyes(A)
This is what my stash_json outputs when put through pprint.
You probably want something along the lines of this:
def get_reviewers(stash_json):
reviewers = ""
for item in stash_json["reviewers"]:
if item["approved"]:
reviewers += item["user"]["displayName"] + "(A)" + ", "
else:
reviewers += item["user"]["displayName"] + ", "
reviewers = reviewers[:-2]
return reviewers
I think part of your confusion comes from the fact that "reviewers" is a list of dict elements, and each dict element has a key-value approved, but also a key "user" which value itself is another dict.
Read the JSON file carefully, and for debugging purposes, use plenty of
print(...)
print(type(...)) # whether something is a dict, list, str, bool etc
or
from pprint import pprint # pretty printing
pprint(...)
This looks like a good place to use join and list comprehension:
def get_reviewers(stash_json):
return ", ".join([item['user']['displayName'] + ('(A)' if item['approved'] else '') for item in stash_json['reviewers']])