Python object serialization - python-3.x

I am trying to mimic a dict by using that as the base class. The objective is to meet these conditions:
If 2 arguments on the command line, set a key and value in the object's dictionary;
if 1 argument on the command line, treat it as a key and show the value; if no arguments on the command line, show all keys and values.
Here is my code:
import pickle,os,sys
class ConfigDict(dict):
def __init__(self, filename):
self._filename = filename
if not os.path.exists(self._filename):
with open(self._filename,"wb") as fh:
pickle.dump({}, fh)
with open(self._filename,"rb") as fh:
self.update(pickle.load(fh))
def __setitem__(self, key, value):
dict.__setitem__(self,key,value)
with open(self._filename,"wb") as fh:
pickle.dump(self, fh)
def __getitem__(self,key):
return dict.__getitem__(self,key)
cd = ConfigDict('first.pickle')
# if 2 arguments on the command line,
# set a key and value in the object's dictionary
if len(sys.argv) == 3:
key, value = sys.argv[1], sys.argv[2]
print('writing data: {0}, {1}'.format(key, value))
cd[key] = value
# if 1 argument on the command line, treat it as a key and show the value
elif len(sys.argv) == 2:
print('reading a value')
key = sys.argv[1]
print('the value for {0} is {1}'.format(sys.argv[1], cd[key]))
# if no arguments on the command line, show all keys and values
else:
print('keys/values:')
for key in cd.keys():
print(' {0} = {1}'.format(key, cd[key]))
I am able to write to the file, however, when i try to retrive the value for a given key, i hit the error (only the end of stack trace shown):
with open(self._filename,"wb") as fh:
AttributeError: 'ConfigDict' object has no attribute '_filename'
But, i already set the _filename in __init__. What am i missing ?

Well, this is a tricky one - the problem seems to be with
pickle.load(fh) and NOT with self.update(
try this in two lines
...
with open(self._filename,"rb") as fh:
tmp = pickle.load(fh)
self.update(tmp)
...
this would fail at tmp =, so it's the object you're un-pickling that's failing. An easy fix would be to do pickle.dump(dict(self), fh), when serialising your things. Though this whole approach seems "forced" to me. Fully working version:
import pickle,os,sys
class ConfigDict(dict):
def __init__(self, filename):
self._filename = filename
if not os.path.exists(self._filename):
with open(self._filename,"wb") as fh:
pickle.dump({}, fh)
with open(self._filename,"rb") as fh:
self.update(pickle.load(fh))
def __setitem__(self, key, value):
dict.__setitem__(self,key,value)
with open(self._filename,"wb") as fh:
pickle.dump(dict(self), fh)
def __getitem__(self,key):
return dict.__getitem__(self,key)
cd = ConfigDict('first.pickle')
# if 2 arguments on the command line,
# set a key and value in the object's dictionary
if len(sys.argv) == 3:
key, value = sys.argv[1], sys.argv[2]
print('writing data: {0}, {1}'.format(key, value))
cd[key] = value
# if 1 argument on the command line, treat it as a key and show the value
elif len(sys.argv) == 2:
print('reading a value')
key = sys.argv[1]
print('the value for {0} is {1}'.format(sys.argv[1], cd[key]))
# if no arguments on the command line, show all keys and values
else:
print('keys/values:')
for key in cd.keys():
print(' {0} = {1}'.format(key, cd[key]))

Related

How to make x variable change each time and read its value from txt file

I am working on my undergraduate project and this is my first time using Python to control a parrot bebop 2 drone. I have a variable x(an int) and I want to read its value from a file. In the mean time I want the program to read this file continuously; what I mean is that my text file input will be changed each time and I want the Python code to catch this change and change the value x.
For example:
if x is assigned 1 from the text file --> then the drone takes off.
in the mean time after x is assigned the value 1, I want it to be assigned 2 automatically and do the second command, for example: move to the left (but without disconnecting the drone "the first command")
here is my code, but I had a lot of problems with it, it checks the value, but no commands work after it knows the value of x:
bebop = Bebop()
print("connecting")
success = bebop.connect(10)
print(success)
f = open('EEGresults.txt')
lines = f.readlines()
list_of_elements = []
for line in lines:
list_of_elements += map(int, line.split())
f.close()
print (list_of_elements)
x = list_of_elements[1]
bebop.smart_sleep(5)
if x == 1:
print ("Yay! This number is = 1")
bebop.safe_takeoff(3)
else:
if x == 2:
print ("Yay! This number is = 2")
bebop.move_relative(0,0,0,1.6)
I expect that the code will read the value of x from text file directly and continuously and at the same time it will run the commands depending what the value of x that it receives.
I donĀ“t know how to use Bebop but I whould use something like this...
First I would create an object to store the data from your file. So you need something like an onValueChanged callback. You have to define this object on your own:
class NotifierVariable():
def __init__(self):
self.__value = 0
self.__Listener = list()
#NotifierVariable.setter
def set(self, value):
if(value != self.__value):
self.__value = value
for callback in self.__Listener:
callback(self.__value)
#property
def get(self):
return self.__value
def addListener(self, callback):
self.__Listener.append(callback)
You can use it in the following way:
class NotifierVariable():
def __init__(self):
self.__value = 0
self.__Listener = list()
def set(self, value):
if(value != self.__value):
self.__value = value
for callback in self.__Listener:
callback(self.__value)
def get(self):
return self.__value
def addListener(self, callback):
self.__Listener.append(callback)
def Func(value):
print(value)
if __name__ == '__main__':
x = NotifierVariable()
x.addListener(Func)
x.set(10)
Now you have to read the file periodicly:
while(True):
with open('EEGresults.txt') as File:
lines = File.readlines()
list_of_elements = []
for line in lines:
list_of_elements += map(int, line.split())
print (list_of_elements)
x.set(list_of_elements[1])
time.sleep(10)
You use the callback to send the command to your drone. The file is periodicly read out every 10 seconds (you can change it) and update your x variable. A callback is triggered if the value got changed and then you can send a command, based on the input, to your drone.

How to print all the highest value places

I cannot figure out how to get python to print all the highest values as it only prints the first one it encounters.
It takes standard input from a file that has on a few lines the following:
89 Michael Dunne (grade name)
I know I can use the zip function but I cannot figure out how only print the name from it
If I add "highstudents = sorted(zip(grade,name),reverse=True)" it sorts from high to low but I do not know how to filter the name out as it prints as "(89, 'Pepe')"
The code below is the following attempt so far.
import sys
def topgrade(x):
s = max(x)
return s
def main():
s = sys.argv[1]
grade=[]
name = []
try:
with open(s,'r') as studata:
for line in studata:
try:
line = line.strip()
grade.append(int(line[0:2]))
name.append(line[3::])
except ValueError:
print("Invalid mark",line[0:2],"encountered. Skipping.")
top = topgrade(grade)
a = grade.index(top)
print("Best students:",name[a])
print("Best mark:",top)
except FileNotFoundError:
print("File not found:",s)
if __name__ == '__main__':
main()
Rather than trying to keep the students and marks in 2 separate lists (with the risk that they get out of step) it is better to use a dictionary - where the key is the mark and the value is a list of the student(s) who obtained that mark.
Then it is a simple task of just printing out the highest key, and the associated list of students. I'm using defaultdict as an easier option than having to create or append to the list for each value.
from collections import defaultdict
import sys
def main():
s = sys.argv[1]
grades = defaultdict(list)
try:
with open(s,'r') as studata:
for line in studata:
try:
line = line.strip()
grades[int(line[0:2])].append(line[3::])
except ValueError:
print("Invalid mark",line[0:2],"encountered. Skipping.")
top_mark = max(grades.keys())
print("Best students:{}".format(','.join(grades[top_mark])))
print("Best mark: {}".format(top_mark))
except FileNotFoundError:
print("File not found:",s)
if __name__ == '__main__':
main()

Python3: Edit dictionary class instance variable

class myClass:
def __init__(self):
self.myClassDict = {}
def ADD_DictPair(self, Value, Key):
#Per ShadowRanger's Solution (Solved)
#self.myClassDict[Value] = Key #Wrong Code
self.myClassDict[Key] = Value #Correct Code
def get_myDict(self):
return self.myClassDict
InstanceOfmyClass = myClass()
InstanceOfmyClass.ADD_DictPair("Value1","Key1")
InstanceOfmyClass.ADD_DictPair("Value2","Key3")
InstanceOfmyClass.ADD_DictPair("Value3","Key3")
print(InstanceOfmyClass.get_myDict()["Key1"])
Desired Output: "Value1"
Error: print(InstanceOfmyClass.get_myDict()["Key1"])
KeyError: 'Key1'
Python3 in Windows // Sublime Text 3
My goal is to interact with the dictionary through it's class method to Add, Call, and Edit values.
def ADD_DictPair(self, Value, Key):
#Per ShadowRanger's Solution (Solved)
#self.myClassDict[Value] = Key #Wrong Code
self.myClassDict[Key] = Value #Correct Code

Write a program that wraps a file to a given line length

I am trying to get it to read the file and convert the lines to words then append the word to a line of a given length. and return the text. This is what I have so far.
def file(file_name):
''' gets users file and checks its validity'''
try:
open(file_name).readlines()
except IOError:
print('File not found')
else:
file = file_name.split()
return file
def column_length(width):
'''gets column width and checks its validity'''
try:
if int(width) >= 1:
return int(width)
else:
print('illegal value')
except ValueError:
print('Illegal value')
def main():
file_name = input('Input file name? ')
width = input('column width? ')
lines = []
line = ''
for i in file_name:
if len(i) + len(line) > int(width):
lines.append(line)
line = ''
line = line + i + ' '
if i is file_name[-1]: lines.append(line)
return '\n'.join(lines)
if __name__ == "__main__":
main()
When I run the code, it seems to skip out the first two functions and doesn't return any text.
If you know where I'm going wrong please let me know.
Thank you.
this uses a great answer from here
def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
for i in xrange(0, len(l), n):
yield l[i:i+n]
with open('in_file.txt') as in_file, open('out_file.txt', 'w') as out_file:
for in_line in in_file:
for out_line in chunks(in_line, width)
out_file.write(out_line + '\n')
Also, very interesting read is the implementation of text justification using dynamic programing. MIT has some great lecture slides online about the subject but this stack thread has most of it. It's similar to the algorithm latex uses to make all text look "pretty". It expands on your idea of text wrapping and adds the feature of justification (it adds whitespaces to make it look as best as possible).
Your code does skip the first two functions, it only defines them. You need to call them from somewhere afterwards, like you did with themain() function. There's no apparent output because the code never does anything with the lines themain()function returns (such asprintthem).
You might want to consider using Python's built-in moduletextwrapto do this sort of text processing. Here's a simple example illustrating its use:
import os
import textwrap
def get_file_name():
""" Get file name and checks its validity. """
file_name = input('Input file name? ')
if not os.path.isfile(file_name):
raise FileNotFoundError('"%s"' % file_name)
return file_name
def get_column_width():
""" Get column width and checks its validity. """
width = int(input('Column width? '))
if width < 1:
raise ValueError('column width must be greater than zero')
return width
def line_wrap(file_name, width):
""" Read blank line delimited paragraphs of text from file and wrap them to
the specified width.
"""
wrapped_lines = []
with open(file_name) as input_file:
lines = ''
for line in input_file:
lines += line
if not line.rstrip(): # blank line?
wrapped_lines.extend(textwrap.wrap(lines, width) + ['\n'])
lines = ''
if lines: # last paragraph need not be followed by blank line
wrapped_lines.extend(textwrap.wrap(lines, width))
return wrapped_lines
def main():
file_name = get_file_name()
width = get_column_width()
wrapped_lines = line_wrap(file_name, width)
print('\n'.join(wrapped_lines))
if __name__ == "__main__":
main()

Functions and Dictionary in Python

def build_dictionary(infile):
count_dict={}
for line in infile:
line=line.strip()
if len(line) and line[0]!="-":
lst=line.split(",")
lastname=lst[0].strip()
for lastname in lst:
if lastname not in count_dict:
count_dict[lastname]=1
else:
count_dict[lastname]=count_dict[lastname]+1
return count_dict
def main():
import os.path
while True:
try:
name1=input("Enter input name:")
infile=open(name1,"r")
result=build_dictionary(infile)
print(result)
break
except:
print("Error in code")
main()
I have this program and I want it to take a file that contains last name,first name, take the last names and see how many times they appear in the dict. the only problem i have is it counts the first lastname then stops, whyy isnt it going through the entire dictionary
Replace your build_dictionary method with this:
def build_dictionary(infile):
count_dict={}
for line in infile:
line=line.strip()
if len(line) and line[0]!="-":
lst=line.split(",")
lastname=lst[0].strip()
if lastname not in count_dict:
count_dict[lastname]=1
else:
count_dict[lastname]=count_dict[lastname]+1
return count_dict

Resources