object has no attributes. New to classes in python - python

import praw
import time
class getPms():
r = praw.Reddit(user_agent="Test Bot By /u/TheC4T")
r.login(username='*************', password='***************')
cache = []
inboxMessage = []
file = 'cache.txt'
def __init__(self):
cache = self.cacheRead(self, self.file)
self.bot_run(self)
self.cacheSave(self, self.file)
time.sleep(5)
return self.inboxMessage
def getPms(self):
def bot_run():
inbox = self.r.get_inbox(limit=25)
print(self.cache)
# print(r.get_friends())#this works
for message in inbox:
if message.id not in self.cache:
# print(message.id)
print(message.body)
# print(message.subject)
self.cache.append(message.id)
self.inboxMessage.append(message.body)
# else:
# print("no messages")
def cacheSave(self, file):
with open(file, 'w') as f:
for s in self.cache:
f.write(s + '\n')
def cacheRead(self, file):
with open(file, 'r') as f:
cache1 = [line.rstrip('\n') for line in f]
return cache1
# while True: #threading is needed in order to run this as a loop. Probably gonna do this in the main method though
# def getInbox(self):
# return self.inboxMessage
The exception is:
cache = self.cacheRead(self, self.file)
AttributeError: 'getPms' object has no attribute 'cacheRead'
I am new to working with classes in python and need help with what I am doing wrong with this if you need any more information I can add some. It worked when it was all functions but now that I attempted to switch it to a class it has stopped working.

Your cacheRead function (as well as bot_run and cacheSave) is indented too far, so it's defined in the body of your other function getPms. Thus it is only accessible inside of getPms. But you're trying to call it from __init__.
I'm not sure what you're trying to achieve here because getPms doesn't have anything else in it but three function definitions. As far as I can tell you should just take out the def getPms line and unindent the three functions it contains so they line up with the __init__ method.

Here are few points:
Unless you're explicitly inheriting from some specific class, you can omit parenthesis:
class A(object):, class A():, class A: are equivalent.
Your class name and class method have the same name. I'm not sure does Python confuse about this or not, but you probably do. You can name your class PMS and your method get, for example, so you'll obtain PMS.get(...)
In the present version of indentation cacheRead and cacheSave functions are simply inaccessible from init; why not move them to generic class namespace?
When calling member functions, you don't need to specify self as the first argument since you're already calling the function from this object. So instead of cache = self.cacheRead(self, self.file) you have to do it like this: cache = self.cacheRead(self.file)

Related

Why is my program returning NameError: name 'self' is not defined as the error

I'm trying to get a program to tell me how many posts I've liked using the InstagramAPI module. It's returning NameError: name 'self' is not defined and I'm not sure why.
This is my code:
from InstagramAPI import InstagramAPI
import time, json, re
import json
import requests
import os
username = ''
password = ''
i = InstagramAPI(username, password)
i.login()
def getTotalLikedMedia(self, scan_rate=1):
next_id = ''
liked_items = []
for x in range(0, scan_rate):
temp = self.getLikedMedia(next_id)
temp = self.LastJson
try:
next_id = temp["next_max_id"]
for item in temp["items"]:
liked_items.append(item)
except KeyError as e:
break
return liked_items
getTotalLikedMedia
self represents the instance of the class. By using the argument bound to the name self we can access the attributes and methods of the class.
You appear to be defining a method without the class it is supposed to be a method of.
class something:
def __init__(self, something):
self.something = something
ins = something()
Without posting entire traceback it is impossible to know what really happened. I guess that the code you posted is not how it really looks like on your computer. It seems like a method definition but here it is just a plain function, where self is just an argument called... well, self. Technically nothing is wrong with that, and calling that method would probably result in raising AttributeError, when the interpreter tries to execute line temp = self.getLikedMedia(next_id), unless you passed as self some object that does have the method getLikedMedia().

Python3: How to save data, when the destructor is called

I actually have a question on Python3. I want to save the attributes of a class in a file, when the destructor is called. How can I do that?
I tried to do it like this:
def __del__:
file = open("test.dat", "w")
file.write("Hello")
file.close()
That code doesn't work. I've already read, that you shouldn't use it, but I actually didn't find a alternative which works. Can anybody help me?
Thanks in advance!
to use that code it needs to be part of a class:
class Test():
def __init__(self):
self.data = "Hello"
def __del__(self):
with open('text.txt', mode='w') as file:
file.write(self.data)
if __name__ == '__main__':
def something():
obj = Test() # obj is deleted when function exits as it becomes out of scope
something()
obj = Test()
del obj # also works because we explicitly delete the object
note that while this method does work, it cannot always be relied upon to always be executed, for example if a sys.exit is called

Accessing class file from multiple methods in Python

My question relates mostly to how you use the with keyword in a class in Python.
If you have a Class which contains a file object, how do you use the with statement, if at all.
For example, I don't use with here:
class CSVLogger:
def __init__(self, rec_queue, filename):
self.rec_queue = rec_queue
## Filename specifications
self.__file_string__ = filename
f = open(self.__file_string__, 'wb')
self.csv_writer = csv.writer(f, newline='', lineterminator='\n', dialect='excel')
If I then do things to the file in another method, For example:
def write_something(self, msg):
self.csv_writer(msg)
Is this suitable? Should I include the with somewhere? I'm just afraid that one the __init__ exits, the with exits and might close the file?
Yes, you are correct with automatically closes the file when its scope ends, so if you use with statement in your __init__() function, the write_something function would not work.
Maybe you can use the with statement in the main part of the program, and instead of opening the file in __init__() function you can pass in the file object as a parameter to the __init__() function. and then do all operations you would like to do in the file within the with block.
Example -
Class would look like -
class CSVLogger:
def __init__(self, rec_queue, filename, f):
self.rec_queue = rec_queue
## Filename specifications
self.__file_string__ = filename
self.csv_writer = csv.writer(f, newline='', lineterminator='\n', dialect='excel')
def write_something(self, msg):
self.csv_writer(msg)
The main program may look like -
with open('filename','wb') as f:
cinstance = CSVLogger(...,f) #file and other parameters
.... #other logic
cinstance.write_something("some message")
..... #other logic
Though if this complicates thing a-lot, you are better off not using the with statement and rather making sure that you close the file when when its need is over.

python: Organizing object model of an application

I have the following problem. My application randomly takes different files, e.g. rar, zip, 7z. And I have different processors to extract and save them locally:
Now everything looks this way:
if extension == 'zip':
archive = zipfile.ZipFile(file_contents)
file_name = archive.namelist()[0]
file_contents = ContentFile(archive.read(file_name))
elif extension == '7z':
archive = py7zlib.Archive7z(file_contents)
file_name = archive.getnames()[0]
file_contents = ContentFile(
archive.getmember(file_name).read())
elif extension == '...':
And I want to switch to more object oriented approach, with one main Processor class and subclasses responsible for specific archives.
E.g. I was thinking about:
class Processor(object):
def __init__(self, filename, contents):
self.filename = filename
self.contents = contents
def get_extension(self):
return self.filename.split(".")[-1]
def process(self):
raise NotImplemented("Need to implement something here")
class ZipProcessor(Processor):
def process(self):
archive = zipfile.ZipFile(file_contents)
file_name = archive.namelist()[0]
file_contents = ContentFile(archive.read(file_name))
etc
But I am not sure, that's a correct way. E.g. I can't invent a way to call needed processor based on the file extension, if following this way
A rule of thumb is that if you have a class with two methods, one of which is __init__(), then it's not a class but a function is disguise.
Writing classes is overkill in this case, because you still have to use the correct class manually.
Since the handling of all kinds of archives will be subtly different, wrap each in a function;
def handle_zip(name):
print name, 'is a zip file'
return 'zip'
def handle_7z(name):
print name, 'is a 7z file'
return '7z'
Et cetera. Since functions are first-class objects in Python, you can use a dictionary using the extension as a key for calling the right function;
import os.path
filename = 'foo.zip'
dispatch = {'.zip': handle_zip, '.7z': handle_7z}
_, extension = os.path.splitext(filename)
try:
rv = dispatch[extension](filename)
except KeyError:
print 'Unknown extension', extension
rv = None
It is important to handle the KeyError here, since dispatch doesn't contain all possible extensions.
An idea that might make sense before (or instead) of writing a custom class to perform your operations generally, is making sure you offer a consistent interface to archives - wrapping zipfile.ZipFile and py7zlib.Archive7z into classes with, for example, a getfilenames method.
This method ensures that you don't repeat yourself, without needing to "hide" your operations in a class, if you don't want to
You may want to use a abc as a base class, to make things extra clear.
Then, you can simply:
archive_extractors= {'zip':MyZipExtractor, '7z':My7zExtractor}
extractor= archive_extractors[extension]
file_name = extractor.getfilenames()[0]
#...
If you want to stick to OOP, you could give Processor a static method to decide if a class can handle a certain file, and implement it in every subclass. Then, if you need to unpack a file, use the base class'es __subclasses__() method to iterate over the subclasses and create an instance of the appropriate one:
class Processor(object):
#staticmethod
def is_appropriate_for(name):
raise NotImplemented()
def process(self, name):
raise NotImplemented()
class ZipProcessor(Processor):
#staticmethod
def is_appropriate_for(name):
return name[-4:] == ".zip"
def process(self, name):
print ".. handling ", name
name = "test.zip"
handler = None
for cls in Processor.__subclasses__():
if cls.is_appropriate_for(name):
handler = cls()
print name, "handled by", handler

Best way to mix and match components in a python app

I have a component that uses a simple pub/sub module I wrote as a message queue. I would like to try out other implementations like RabbitMQ. However, I want to make this backend change configurable so I can switch between my implementation and 3rd party modules for cleanliness and testing.
The obvious answer seems to be to:
Read a config file
Create a modifiable settings object/dict
Modify the target component to lazily load the specified implementation.
something like :
# component.py
from test.queues import Queue
class Component:
def __init__(self, Queue=Queue):
self.queue = Queue()
def publish(self, message):
self.queue.publish(message)
# queues.py
import test.settings as settings
def Queue(*args, **kwargs):
klass = settings.get('queue')
return klass(*args, **kwargs)
Not sure if the init should take in the Queue class, I figure it would help in easily specifying the queue used while testing.
Another thought I had was something like http://www.voidspace.org.uk/python/mock/patch.html though that seems like it would get messy. Upside would be that I wouldn't have to modify the code to support swapping component.
Any other ideas or anecdotes would be appreciated.
EDIT: Fixed indent.
One thing I've done before is to create a common class that each specific implementation inherits from. Then there's a spec that can easily be followed, and each implementation can avoid repeating certain code they'll all share.
This is a bad example, but you can see how you could make the saver object use any of the classes specified and the rest of your code wouldn't care.
class SaverTemplate(object):
def __init__(self, name, obj):
self.name = name
self.obj = obj
def save(self):
raise NotImplementedError
import json
class JsonSaver(SaverTemplate):
def save(self):
file = open(self.name + '.json', 'wb')
json.dump(self.object, file)
file.close()
import cPickle
class PickleSaver(SaverTemplate):
def save(self):
file = open(self.name + '.pickle', 'wb')
cPickle.dump(self.object, file, protocol=cPickle.HIGHEST_PROTOCOL)
file.close()
import yaml
class PickleSaver(SaverTemplate):
def save(self):
file = open(self.name + '.yaml', 'wb')
yaml.dump(self.object, file)
file.close()
saver = PickleSaver('whatever', foo)
saver.save()

Categories