I'd like to schedule a method using the schedule module but it doesn't work.
The error message is as follows:
Warning: Missing Argument 'self'.
Here is my code:
def p_b(self):
do
print('hello')
do
do
schedule.every().minute.do(p_b)
while True:
schedule.run_pending() # error comes out.
time.sleep(1)
As the error indicates, you added "self" to the method. Self represent an instance of a class that is passed automatically when you make a call, see here fore more info.
So try to remove the self parameter and it should just work:
import schedule
import time
def p_b():
print('hello')
schedule.every().minute.do(p_b)
while True:
schedule.run_pending()
time.sleep(1)
Edit
If you do have that method inside a class and you have the scheduler outside, you need to call it from an instance of the class e.g.:
import schedule
import time
class SomeClass:
def p_b(self):
print('hello')
if __name__=='__main__':
some_class = SomeClass()
schedule.every().minute.do(some_class.p_b)
while True:
schedule.run_pending()
time.sleep(1)
Related
I'm new to threading and python. I would like to understand how to pass multiple arguments from one class to another class in python using threading.
I'm using a main thread to call a class- Process then inside the run I'm doing some business logic and calling another class- build using thread and passing multiple arguments.
The run of build class is getting executed but Inside the build class, I'm unable to access those arguments and hence not able to proceed further.
Not sure if my approach is right? Any suggestions will be appreciated.
Below is my main class :
from threading import Thread
import logging as log
from process import Process
if __name__ == '__main__':
try:
proc = Process()
proc.start()
except Exception as e:
#log some error
Inside Process:
#all the dependencies are imported
class Process(Thread):
'''
classdocs
'''
def __init__(self):
'''
Constructor
'''
Thread.__init__(self)
#other intializations
def run(self):
#some other logic
self.notification(pass_some_data)
#inside notification I'm calling another thread
def notification(self,passed_data):
#passed data is converted dict1
#tup1 is being formed from another function.
#build is a class, and if i don't pass None, i get groupname error.
th = build(None,(tup1,),(dict1,))
th.start()
#inside build
class build(Thread):
def _init_(self,tup1,dict1):
super(build,self).__init__(self)
self.tup1 = tup1
self.dict1 = dict1
def run(self):
#some business logic
#I'm unable to get the arguments being passed here.
I have the following code and store in a file called run_thread.py
from mymodule import Builder
def run_thread():
threads = []
for chunk in chunks:
thread = threading.Thread(target=Builder.work, args=(a, b, c))
threads.append(thread)
try:
thread.start()
except:
pass
for thread in threads:
try:
thread.join()
except:
pass
When I try to mock/patch Builder.work in my unittest, the original Builder.work still run, which is NOT what I'm expecting.
import unittest
from ddt import ddt, data, unpack
from mock import patch
#ddt
class TestRunThread(unittest.TestCase):
#patch('run_thread.Builder.work')
def test_run_thread(self, mock_work):
run_thread()
It did not work for me because Builder.work() is a static method.
When patch a class function, property, class attribute, this is used according to document
#patch.object(Builder, 'work')
def test_run_thread(self, mock_work):
# this is tested to work with static method
mock_work.return_value = ['a', 'bbbb']
class property and class attribute(not instance member) can also use
#patch('mymodule.Builder.class_attribute_or_property')
def test_mock_cls_attribute_or_property(mock_attribute):
# this patch method tested not working for static method
import sys
from threading import Thread
is_online=1
class CommandListenerThread(Thread):
global is_online
def run(self):
while is_online:
next_command=sys.stdin.readlines();
if next_command == 'exit':
is_online=0
else:
print next_command
listener=CommandListenerThread()
listener.start()
When I run this python code,it shows an error: "UnboundLocalError: local variable 'is_online' referenced before assignment"
I tested another code which uses the same way to access the global variable inside a class,and it works fine. So,what is wrong with this specific code?
the code may look weird which using a thread to listen the command line,but it is just
a part of my program which gets an error when I run the whole program.
thank you guys
Move global is_online into run() to solve the error.
To address your other question (in a comment below), why not make it a static class variable ?
class CommandListenerThread(Thread):
is_online = 1
def run(self):
print CommandListenerThread.is_online
In case that you have to use another code with a global is_online, you can take the DI (dependency injection) approach as follows:
import sys
from threading import Thread
is_online = 2
class CommandListenerThread(Thread):
def __init__(self, is_online):
super(CommandListenerThread, self).__init__()
CommandListenerThread.is_online = is_online # now it's a static member
# if you want to make it an instance member use self.is_online
def run(self):
print CommandListenerThread.is_online
listener=CommandListenerThread(is_online) # inject the value to the constructor
listener.start()
First of all, here are my two python files:
sred.py:
import _thread,time
class Thread:
def __init__(self,time:int,say:str):
self.time=time
self.say=say
def create():
id = _thread.get_ident()
for i in range(5):
print("HALLO", id)
return
from sred import Thread
import time,_thread
_thread.start_new_thread(Thread.create,())
The second one:
main.py
from sred import Thread
import time,_thread
_thread.start_new_thread(Thread.create,())
when executing this it doesn't print anything out, why?
UPDATE:
import _thread
class Thread:
#classmethod
def create():
id = _thread.get_ident()
for i in range(5):
print("HALLO", id)
return
main.py:
from sred import Thread
import time,_thread
_thread.start_new_thread(Thread().create,())
Is this now right, or is there still something wrong?
The create method is missing self as a parameter -- it looks like it should also be a #classmethod if you want to call it as it's written now. Note that your __init__ method is never getting called, because you never instantiate any Thread objects. You may want it to read:
_thread.start_new_thread(Thread().create, ())
i.e., instantiate a thread, then pass its create method to be executed in the new thread. I'm not sure what's happening, but I suspect that something is erroring and the stacktrace is being suppressed by something.
Also, you need to delete the space after the for statement -- it's significant, and it should be throwing you a syntax error about an unexpected indent.
EDIT:
This version runs on my machine:
import _thread
class Thread:
def create(self):
id = _thread.get_ident()
for i in range(5):
print("HALLO", id)
return
_thread.start_new_thread(Thread().create, ())
I have just started learning python and am getting caught up. I come from mostly C background.
class Alarm:
def timer():
def main():
print ("Timer has Started")
main()
I always get a silly error when I try to run this code:
alarm > python alarm.py
File "alarm.py", line 5
def main():
^
IndentationError: expected an indented block
You have an empty def
def timer():
use
def timer():
pass
instead.
Learn about the pass statement, main is usually not part of the class.
A global (module level) main() function is simpler than an Alarm.main() class method. Usually, main() functions come at module level.
class Alarm:
def timer():
pass
def main():
print ("Timer has Started")
main()
I think you want to use __init__ though, which is the constructor...
class Alarm:
def timer(self):
print('timer has started')
def __init__(self):
print('constructor')
self.timer()
x = Alarm()
constructor
timer has started
My example differs from the others in that I'm actually instantiating a new object.
Notes:
specify self as the first argument to any method defined in the class
__init__ is the method to define for the constructor
invoke the class by doing variableName = className() like you would invoke a function, no new keyword
if you have an empty function, use the pass keyword like def foo(self): pass
Invoking main() will give an undefined function error, as it is a Alarm method.
IMHO the right form you should use is the following:
class Alarm:
def timer():
pass
#staticmethod
def main():
print ("Timer has Started")
if __name__ == "__main__" :
Alarm.main()
try deindent main() and add pass to timer and define an init method:
class Alarm():
def __init__(self):
print ("Timer has Started")
<shell>$ Alarm()
Your timer function is not defined. (And your space/tab indentation may be mixed)
See the tutorial (classes) for more details on classes.
class Alarm:
def timer(self):
pass
def main(self):
print ("Timer has Started")
if __name__ == '__main__':
class_inst = Alarm()
class_inst.main()
If you getting into python read PEP8.
Also, using pylint helps, it will point out indentation and many other errors you'll run across before you 'execute' your code.
As others have pointed out, you have a syntax error because timer() has no body.
You don't need to use main() in python at all. Usually people use it to indicate that the file is the top level program and not a module to be imported, but it is just by convention
You may also see this idiom
def main():
blah blah
if __name__ == "__main__":
main()
Here __name__ is a special variable. If the file has been imported it will contain the module name, so the comparison fails and main does not run.
For the top level program __name__ contains "__main__" so the main() function will be run.
This is useful because sometimes your module might run tests when it is loaded as a program but you don't want those test to run if you are importing it into a larger program
In Python, you don't need to define everything as a class. There's nothing to encapsulate in this code, so there's no reason to define an Alarm class. Just have the functions in a module.
Thanks for all the help everybody. I was making a little alarm/timer to remind me to get up and take a walk every now and then. I got most of it working, and it works great. Checked it against a stop watch and it works great.
import time
def timer(num):
seconds = num*60
print (num , "minutes", seconds , "seconds")
while (seconds > 0):
print (seconds, "seconds")
time.sleep(1)
seconds = seconds-1
print ("Time to get up and take a WALK!!!!")
main()
def main():
number = input("Input time : ")
int(number)
timer(number)
if __name__ == '__main__':
main()