I'm inheriting a class with an init method already set.
I'd like to add an arg to this method, as well as a few lines of code.
I suspect that I can use super to do this, but am not quite sure how and the examples I've found don't always make sense to me.
Example code AND EXPLANATION:
The bot module has 2 classes: Bot, and BotStreamListener
BotStreamListener inherits from tweepy.StreamListener, which already has init defined
I need to append an arg and some code to this classmethod so that methods in the BotStreamListener class know the instantiated instance of the Bot class. (in the example below, it's mybot).
...
def main():
try:
me = api.me()
print "Starting userstream for %s ( %s )" %(me.name, me.screen_name)
mybot = bot.bot(api)
#What it looks like now
stream = tweepy.Stream(auth, bot.BotStreamListener(api))
#What i would like it to be able to handle
stream = tweepy.Stream(auth, bot.BotStreamListener(api, mybot))
In short, I would like to add a few more args and some code to an inherited init classmethod, without redefining the method.
I'm using python 2.7, any help is apreciated.
I'm not familiar with tweepy other than knowing what it is, but this should get you started:
# bot.py
class BotStreamListener(StreamListener):
def __init__(api, bot):
super(self.__class__, self).__init__(api)
# Do your stuff
self.bot = bot
# Do more of your stuff
mybot = bot.bot(api)
bsl = BotStreamListener(api, mybot)
Related
entry_point.py
from other_file import UserBehaviour
class ApiUser(HttpUser):
tasks = [UserBehaviour]
def on_start(self):
# log in and return session id and cookie
# example: self.foo = "foo"
other_file.py
from entry_point import ApiUser
class UserBehaviour(TaskSet):
#task
def do_something(self, session_id, session_cookie)
# use session id and session cookie from user instance running the taskset
# example: print(self.ApiUser.foo)
NOTE: Going through the documentation, I did find that "the User instance can be accessed from within a TaskSet instance through the TaskSet.user", however all my attempts to import the user into the taskset file led to a "cannot import name 'ApiUser' from 'entry_point'" error. If instead of from entry_point import ApiUser I do from entry_point import *, then I get a name 'ApiUser' is not defined error.
Thank you very much #Cyberwiz for putting me on the right track. I've finally managed to figure out what I was doing wrong... which, as it turns out, was a couple of things.
Firstly, importing ApiUser in other_file.py was incorrect for two reasons: 1) it creates a cyclical dependency, and 2) even if it would eventually work it would import the ApiUser class, not the instance of the ApiUser class.
Secondly, I was previously getting a module locust.user has no attribute {name} error, and that was because my code looked like this:
class UserBehaviour(TaskSet):
# do something with user.foo
Having figured this out, I honestly have no idea why I thought the above would work. I've changed my code to reflect the example below and everything now works like a charm:
class UserBehaviour(TaskSet):
#task
def do_something(self):
# do something with self.user.foo
I am writing Python code (based on PyQt5 signals and slots). I need to make my code "Scriptable". By scriptable I mean the user can utilize the internal objects himself in a user-defined python script to develop/automate some functions,..etc. But I have no idea of how to implement it clearly.
I have tried using (exec) function in python in the following way:
user-def.py
def script_entry(main_object_in_my_code):
# Connecting signal from main_object_in_my_code (inherited from QObject) to other functions in this
# file. example:
main_object_in_my_code.event_1.connect(function_1)
#QtCore.pyqtSlot(str)
def function_1 (args):
#do user-defined logic using those args.
then in my script when user want to execute it, he inputs (as example)
source user-def.py
the main script reads the script and uses exec as the following:
with open(script_path) as f:
script = f.read()
exec(script, globals())
the problem is that events are triggered but function function_1 is not executed.
I am sure this is not the right way to do this. So, How can I implement my code to be (scriptable) using user defined scripts?
I would recomend to create a class and extend from it, let the 'user' call the functions when s/he needs.
If you are not in touch with class inheritance check this tutorial
source_def.py
class Main:
def __init__(self):
super(Main, self).__init__()
def script_entry(self, main_object_in_my_code):
main_object_in_my_code.event_1.connect( function_1 )
#QtCore.pyqtSlot(str)
def function_1( self, args ):
#this checks if the function is set
invert_op = getattr(self, "user_function", None)
if callable(user_function):
eval('self.user_function( args )')
user_def.py
from source_def import Main
class UserClass( Main ):
def __init__(self):
super(UserClass, self).__init__()
def user_function(self , args ):
print( args )
Try this
traits_pickle_problem.py
from traits.api import HasTraits, List
import cPickle
class Client(HasTraits):
data = List
class Person(object):
def __init__(self):
self.client = Client()
# dynamic handler
self.client.on_trait_event(self.report,'data_items')
def report(self,obj,name,old,new):
print 'client added-- ' , new.added
if __name__ == '__main__':
p = Person()
p.client.data = [1,2,3]
p.client.data.append(10)
cPickle.dump(p,open('testTraits.pkl','wb'))
The above code reports a dynamic trait. Everything works as expected in this code. However, using a new python process and doing the following:
>>> from traits_pickle_problem import Person, Client
>>> p=cPickle.load(open('testTraits.pkl','rb'))
>>> p.client.data.append(1000)
causes no report of the list append. However, re-establishing the listener separately as follows:
>>> p.client.on_trait_event(p.report,'data_items')
>>> p.client.data.append(1000)
client added-- [1000]
makes it work again.
Am I missing something or does the handler need to be re-established in __setstate__ during the unpickling process.
Any help appreciated. This is for Python 2.7 (32-bit) on windows with traits version 4.30.
Running pickletools.dis(cPickle.dumps(p)), you can see the handler object being referenced:
...
213: c GLOBAL 'traits.trait_handlers TraitListObject'
...
But there's no further information on how it should be wired to the report method. So either the trait_handler doesn't pickle itself out properly, or it's an ephemeral thing like a file handle that can't be pickled in the first place.
In either case, your best option is to overload __setstate__ and re-wire the event handler when the object is re-created. It's not ideal, but at least everything is contained within the object.
class Person(object):
def __init__(self):
self.client = Client()
# dynamic handler
self.client.on_trait_event(self.report, 'data_items')
def __setstate__(self, d):
self.client = d['client']
self.client.on_trait_event(self.report, 'data_items')
def report(self, obj, name, old, new):
print 'client added-- ', new.added
Unpickling the file now correctly registers the event handler:
p=cPickle.load(open('testTraits.pkl','rb'))
p.client.data.append(1000)
>>> client added-- [1000]
You might find this talk Alex Gaynor did at PyCon interesting. It goes into the high points of how pickling work under the hood.
EDIT - initial response used on_trait_change - a typo that appears to work. Changed it back to on_trait_event for clarity.
I had the same problem but came around like this: Imaging I want to pickle only parts of a quiet big class and some of the objects has been set so transient=True so they're not pickled because there is nothing important to save, e.g.
class LineSpectrum(HasTraits):
andor_cam = Instance(ANDORiKonM, transient=True)
In difference to objects which should be saved, e.g.
spectrometer = Instance(SomeNiceSpectrometer)
In my LineSpectrum class, I have a
def __init__(self, f):
super(LineSpectrum, self).__init__()
self.load_spectrum(f)
def __setstate__(self, state): # WORKING!
print("LineSpectrum: __setstate__ with super(...) call")
self.__dict__.update(state)
super(LineSpectrum, self).__init__() # this has to be done, otherwise pickled sliders won't work, also first update __dict__!
self.from_pickle = True # is not needed by traits, need it for myself
self.andor_cam = ANDORiKonM(self.filename)
self.load_spectrum(self.filename)
In my case, this works perfectly - all sliders are working, all values set at the time the object has been pickled are set back.
Hope this works for you or anybody who's having the same problem. Got Anaconda Python 2.7.11, all packages updated.
PS: I know the thread is old, but didn't want to open a new one just for this.
I was trying to include my own functions in mainpage class, but when calling them it's not working at all, so what i did is to create a class for it and included that function in it. and in get () of mainpage class i created an instance for that class and called the function like object_name.function name() but it ain't working
class encipher:
def time_stomp():
t1=time.time()
dt = datetime.now()
dt.now()
stri=""
stri+=(str(dt.minute*dt.microsecond)[0:4])
stri+=(str(dt.second*dt.microsecond)[0:2])
stri+=(str(dt.microsecond)[0:3])
stri+=(str(dt.microsecond)[2:3])
stri+=(str(dt.microsecond)[1:2])
stri+=(str(dt.microsecond)[0:1])
return stri
#-------------------------------------------------------------
def keygen():
key_stri=""
ko=0
datalist_str1=self.time_stomp()
for i in range(6):
key_stri+=((hex(operator.xor(int(datalist_str1[ko:ko+2]),128)).replace("0x","")).zfill(2))
ko+=2
#print "Key:",key_stri
#print "Key:",key_stri
#print "Key:",key_stri
return key_stri
class MainPage(webapp.RequestHandler):
def get(self):
ddes=encipher()
global final_data_hex
global username
global filename
username = self.request.get("name")
filename=self.request.get("filename")
addr=self.request.get("mac")
path="d:/xampp/htdocs/encrypt/"+username+'/'+filename
f1 = open(path, 'r')
#f1=open(path,"r")
string=f1.read()
i=0
addr=addr.replace(":",'')
#self.response.out.write(ddes.keygen())
A python instance method needs to accept at least one parameter, self. "It's not working" is a horrible explanation of a problem; if you'd read your tracebacks you'd see an error about .keygen() accepting 0 arguments with 1 provided.
But yes, there's no reason to encapsulate methods in a class if what you really want is a function.
I figured it out. We can simply include functions out of the class and it will work perfectly.
everyone. Please see example below. I'd like to supply a string to 'schedule_action' method which specifies, what Bot-class method should be called. In the example below I've represented it as 'bot.action()' but I have no idea how to do it correctly. Please help
class Bot:
def work(self): pass
def fight(self): pass
class Scheduler:
def schedule_action(self,action):
bot = Bot()
bot.action()
scheduler = Scheduler()
scheduler.schedule_action('fight')
Use getattr:
class Bot:
def fight(self):
print "fighting is fun!"
class Scheduler:
def schedule_action(self,action):
bot = Bot()
getattr(bot,action)()
scheduler = Scheduler()
scheduler.schedule_action('fight')
Note that getattr also takes an optional argument that allows you to return a default value in case the requested action doesn't exist.
In short,
getattr(bot, action)()
getattr will look up an attribute on the object by name -- attributes can be data or member methods The extra () at the end calls the method.
You could get the method in a separate step, like this, as well:
method_to_call = getattr(bot, action)
method_to_call()
And you can pass arguments to the method in the usual way:
getattr(bot, action)(argument1, argument2)
or
method_to_call = getattr(bot, action)
method_to_call(argument1, argument2)
I'm not sure if it applies in your situation, but you may consider using a function pointer instead of manipulating the strings.
class Bot:
def work(self):
print 'working'
def fight(self):
print 'fightin'
class Scheduler:
def schedule_action(self,action):
bot = Bot()
action(bot)
scheduler = Scheduler()
scheduler.schedule_action(Bot.fight)
scheduler.schedule_action(Bot.work)
Which prints:
fightin
working
If you can do this, it will give you an error about a misspelled function at compile-time when the code is interpreted instead of during run-time. This could shorten your debug cycle for stupid data-entry errors, especially if the actions are done over a span of time. Nothing sucks more than running something overnight and discovering that you had a syntax error in the morning.
class Scheduler:
def schedule_action(self,action):
bot = Bot()
boundmethod = getattr(bot, action)
boundmethod()
def schedule_action(self,action):
bot = Bot()
bot.__getattribute__(action)()
You can also use a dictionary to map methods to actions. For instance:
ACTIONS = {"fight": Bot.fight,
"walk": Bot.walk,}
class Scheduler:
def schedule_action(self, action):
return ACTIONS[action](Bot())