How to access python objects with a dynamic object name? - python

I have a question to one of my python scripts. I'm using the library untangle (https://github.com/stchris/untangle) to import and convert xml config files into the main script.
The problem: I have user informations in the config file for more than one user and I'm using this information in a loop. It works very well, but it makes the script very ugly due to the name of the generated objects from the xml file.
Concrete this means I can't (or I just don't know how) change the name of the object I would like to use dynamic.
The example code is below:
if employee == 0:
if str(configobj.config.modes.employee.employee_1.name.cdata) != '':
display.drawtext(0,0,str(configobj.config.modes.employee.employee_1.name.cdata),"7x13B",255,255,255,True)
if str(configobj.config.modes.employee.employee_1.line1.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_1.line1['x']),
int(configobj.config.modes.employee.employee_1.line1['y']),
if str(configobj.config.modes.employee.employee_1.line2.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_1.line2['x']),
int(configobj.config.modes.employee.employee_1.line2['y']),
if str(configobj.config.modes.employee.employee_1.line3.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_1.line3['x']),
int(configobj.config.modes.employee.employee_1.line3['y']))
displayimage = True
elif employee == 1:
if str(configobj.config.modes.employee.employee_2.name.cdata) != '':
display.drawtext(0,0,str(configobj.config.modes.employee.employee_2.name.cdata),"7x13B",255,255,255,True)
if str(configobj.config.modes.employee.employee_2.line1.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_2.line1['x']),
int(configobj.config.modes.employee.employee_2.line1['y']),
if str(configobj.config.modes.employee.employee_2.line2.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_2.line2['x']),
int(configobj.config.modes.employee.employee_2.line2['y']),
if str(configobj.config.modes.employee.employee_2.line3.cdata) != '':
display.drawtext(int(configobj.config.modes.employee.employee_2.line3['x']),
int(configobj.config.modes.employee.employee_2.line3['y']),
if str(configobj.config.modes.employee.employee_2.image.cdata) != '':
display.showimage(160,0,str(configobj.config.modes.employee.employee_2.image.cdata))
displayimage = True
And this is a lot of repeated code with a changing number. How can I improve this?

Use getattr:
getattr(configobj.config.modes.employee, 'employee_' + str(employee + 1)).name.cdata
You can also create separate variable for employee:
employee = getattr(configobj.config.modes.employee, 'employee_' + str(employee + 1))
print(employee.name.cdata)
print(employee.line1['x'])

Related

Attempting to modify CSV value based on the input received

Below is an example of the code, essentially I am taking input received and attempting to modify an existing CSV value. The problem is the code runs and produces the "print" output as expected, but the values are not being modified to "True" or "False" based on the if and else statements:
def test():
sn_cmn = pd.read_csv('cmn_location.csv')
wan = re.findall(r'Tunnel12', str(router_output)) or re.findall(r'Tunnel13', str(router_output))
hostname = re.search(r'...-....-R.', str(router_output))
hostname_string = str(hostname)
site_code = hostname_string[-13:-10]
if wan == ['Tunnel12'] or wan == ['Tunnel13']:
answer = 'Yes'
if answer == 'Yes':
for site in sn_cmn.u_site_code:
sn_cmn.loc[sn_cmn['u_site_code'] == site_code, 'u_iwan_3'] = 'TRUE'
else:
for site in sn_cmn.u_site_code:
sn_cmn.loc[sn_cmn['u_site_code'] == site_code, 'u_iwan_3'] = 'FALSE'
sn_cmn.to_csv('new_cmn_location.csv')

Accessing and array and nested properties in Python

Sorry, I have searched and not managed to figure out an answer to this - I know there are lots of threads and questions in relation to it but cannot see an answer. Please redirect me or perhaps suggest a solution! TIA
I have an array of objects.
One (4 actually) of the properties of the objects in this array is another class.
Input taken from the user refers to one of the properties in the array which contains an instance of the other class. I simply want to read that data.
class direction():
dest = -1
lock = ''
class room():
roomname = ''
desc = ''
n = direction()
s = direction()
w = direction()
e = direction()
item = ''
rooms = []
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms.append( room() )
rooms[0].roomname = 'outside'
rooms[0].desc = ''
rooms[0].n.dest = 'bathroom'
rooms[0].item = ''
rooms[1].roomname = 'hall'
rooms[1].desc = 'The hallway has doors to the east and south'
rooms[1].s.dest = 2
rooms[1].e.dest = 3
rooms[1].item = ''
and so on..
Now I take input from the user eg: "go n"
and would like to check/read the 'lock' property from the property that relates to the taken direction in the current room. currentRoom is an integer that relates to the LIST element that it links to.
Please do not criticise my lack of constructors. I am trying to keep the code as simple as possible initially and will introduce those later on.
I take input as follows:
print('Your action:')
move = input('>>>').lower().split()
I use the following line of code to check that the taken direction exists in the current room as follows:
if getattr(rooms[currentRoom], move[1]) != '':
and then want to check the lock property for the given direction in the current room. Something like this... (which does not work)
if rooms[currentRoom].move[1].lock != '':
I hope this is clear enough! Many thanks.
if rooms[currentRoom].move[1].lock != '':
This line of code will not work because move[1] is a string. If you wanted to access the variable in the class you would have to call it in the line of code
if rooms[currentRoom].n.lock != '':
A solution would be to get the value stored in the object then as follows
x = getattr(rooms[currentRoom], move[1]) #getattr() returns direction() object
if x.lock != '': #check lock value in direction() object

Issues with pickling in python - items not saving to file once program exits

I am trying to create a python program to save my friends' birthdays and access them easily and check for birthdays each day(I am not great at remembering dates and I never use facebook), but when I add a new birthday it is only accessible until I end the program - it then disappears again. I have been struggling with this for a while now and would really appreciate help fixing the error. Thanks!
import time
import pickle
def main():
birthday_file = open('birthdays_dict.dat','ab')
birthday_doc = open('birthdays_dict.dat','rb')
birthdays = pickle.load(birthday_doc)
date = time.strftime("%m/%d")
again = 'y'
while again.lower() == 'y' or again.lower() == 'yes':
choice = menu_choice()
if choice == 1:
name = add_name()
birthday = add_birthday()
birthdays[name] = birthday
print(name)
print(birthday)
pickle.dump(birthdays,birthday_file)
elif choice == 2:
print('Birthdays today(' + date + '):')
birth_today = {}
for key, value in birthdays.items():
if value == date:
print(key)
elif choice == 3:
search_name = input('Enter name to search: ')
print()
if search_name in birthdays:
print(birthdays[search_name])
if birthdays[search_name] == date:
print('Their birthday is today!')
else:
print('Not found')
else:
print('Not a valid selection!')
print()
again = go_again()
birthday_file.close()
birthday_doc.close()
Your problem is that you keep appending new dicts onto the file instead of replacing the old one, but then at startup you only load the very first one instead of all of them.
To fix this, you need to change this:
birthday_file = open('birthdays_dict.dat','ab')
… to this:
birthday_file = open('birthdays_dict.dat','wb')
But don't do that change on its own, because that will erase the file before you've read the old version!
You probably want to do something like this at the top of the function:
with open('birthdays_dict.dat', 'rb') as birthday_doc:
birthdays = pickle.load(birthday_doc)
I used a with statement so the file will automatically get closed right after the load, so it's definitely safe for us to overwrite it later.
Then later, when you want to write to the file, that's when you open it in w mode to erase the file and overwrite it with the new version—at which point you might as well close it immediately, because if you ever do write to it again, you're going to want to erase it again first, so let's use with again:
with open('birthdays_dict.dat', 'wb') as birthday_doc:
pickle.dump(birthdays, birthday_doc)

Save File Function

So for my intro programming class we have to create a game with a save/load function and I'm trying to test out some code to make sure it works.
For some reason I cannot get the following function to work properly. I've tried going through it line by line in the Idle and it works just fine there but once I try to use the same system in a function it just will not work. Help please?
def save(name,inventory,mapGrid,x,y,enemy):`
choice = 0
file = shelve.open("save_files")
save = {'save1':file['save1'],'save2':file['save2'],'save3':file['save3']}
print("Where would you like to save?")
print("Save 1 -", save['save1']['name'])
print("Save 2 -", save['save2']['name'])
print("Save 3 -", save['save3']['name'])
choice = input("Enter Number:\t")
if choice == 1:
save['save1']['name'] = name
save['save1']['inventory'] = inventory
save['save1']['mapGrid'] = mapGrid
save['save1']['x'] = x
save['save1']['y'] = y
save['save1']['enemy'] = enemy
file['save1'] = save['save1']
file.sync()
if choice == 2:
save['save2']['name'] = name
save['save2']['inventory'] = inventory
save['save2']['mapGrid'] = mapGrid
save['save2']['x'] = x
save['save2']['y'] = y
save['save2']['enemy'] = enemy
file['save2'] = save['save2']
file.sync()
if choice == 3:
save['save3']['name'] = name
save['save3']['inventory'] = inventory
save['save3']['mapGrid'] = mapGrid
save['save3']['x'] = x
save['save3']['y'] = y
save['save3']['enemy'] = enemy
file['save3'] = save['save3']
file.sync()
file.close()
print("Game Saved")
EDIT: After running the function it should save the dictionary to file['save#'] and allow me to access the data later on, but the data doesn't save to the shelve file and when I try to access it again there's nothing there. ((Sorry should have put this in right off the bat))
For example if I run the save() function again it should display the name associated with the save file, but it just shows 'EMPTY'.
The basic thing I have the save_files set to is
file['save#'] = {'name':'EMPTY'}
Since your if statements are comparing int, make sure that choice is also an integer. It's possible that choice is actually a string, in which case none of the comparisons will be True. Basically:
choice = int(input("Enter Number:\t"))
Alternatively you could change all comparisons to strings, but the important thing is to assure type consistency in the comparisons

Saving/Loading lists in Python

I am new to python (and programming in general) and am making a database/register for a typical class. I wanted the user to be able to add and remove pupils from the database, I used lists primarily for this but have hit a stump.
Whenever I restart the program the list the user has modified returns back to the defualt list I specified in the code. I looked around the internet and tried to save the list onto a seperate txt file. However the txt file also goes back to the defualt every time I restart the program. I would like you to please give me a way to save the changes made to the list and keep them that way. Here is the code (it's not very good):
def menu():
print "*****************CLASS REGISTER*****************"
print "Press 1 See The List Of Pupils"
print "Press 2 To Add New Pupils"
print "Press 3 To Remove Pupils"
print "Press 0 To Quit \n"
filename = open('pupil.txt','r')
pupil = ["James Steele", "Blain Krontick", "Leeroy Jenkins", "Tanvir Choudrey"]
def see_list(x):
print x
def add_pupil(x):
print "You have chosen to add a new pupil.\n"
option = raw_input("Please type the childs name.")
x.append(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been added to the system."
return x
def delete_pupil(x):
print "You have chosen to remove a pupil.\n"
option = raw_input("Please type the childs name.")
if option in x:
x.remove(option)
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
print option, "has been removed from the system."
else:
print "That person is not in the system."
return x
one = 1
while one != 0:
menu()
option = input()
if option == 1:
see_list(pupil)
elif option == 2:
add_pupil(pupil)
elif option == 3:
delete_pupil(pupil)
elif option == 0:
break
else:
print "That is not a valible choice."
filename = open('pupil.txt','w')
filename.write('\n'.join(pupil))
filename.close()
if option == 0:
quit
Well, you just open the pupil.txt file but never read back its contents. You need something like this:
filename = open('pupil.txt', 'r')
contents = filename.read()
filename.close()
pupil = [name for name in contents.split('\n') if name]
Also, you will need to handle the case when the pupil.txt file does not exist; this can be done with a try..except block around the IO calls.
Finally, as one of the comments has mentioned above, have a look at the pickle module, which lets you store a Python object in a file in Python's internal format (which is not really readable, but saves you a lot of hassle).
Not related to your question directly, but this:
one = 1
while one != 0:
...
is silly. All you need is:
while True:
...
This is what a database is for. Use sqlite - a simple file-based database the libraries for which come bundled with python.

Categories

Resources