Variable not found in asynchronous classes - python

I have a little problem, in fact, I am trying to make the game of life but without searching on google and I would like to make two classes, the first one that proceed the tkinter app and the second one that proceed the game it self (moving cells...).
The fact is, when I try to implement a pause button, it doesn't works because of the while of the game class or its recursive function... Well, the process of the app is completly used by the loop.
I then tried to make it with asynchronous methods and to well understand them I tried with an own example :
`
import asyncio
from async_class import AsyncClass
class Foo():
async def __ainit__(self):
self.test = 'Hi'
return
#
def show(self):
print(self.test)
#
class Bar():
async def __ainit__(self):
return
#
#
async def main():
foo = Foo()
asyncio.create_task(foo.show())
bar = Bar()
if __name__ == '__main__':
asyncio.run(main())
`
Here I then have an error that says : AttributeError: 'Foo' object has no attribute 'test'...
To you have any idea to fix that ? or even a ethod to permit a pause into the game ?
I hope you'll have a solution,
Thx

Related

How to access instance variables from a threaded instance method?

I have been struggling to figure out how to access the the instance variable from an instance method running in a separate thread like in the example below. I thought the loop would be skipped after the test.set_finished method is called from the main thread after 5 seconds.
However my loop keeps counting and I fail to understand why. Would be nice if someone could help me out a little and tell me what I need to do differently or what I'm trying to do is not possible at all.
import time
import concurrent.futures
class TestClass(object):
def __init__(self):
super(TestClass, self).__init__()
self.finished = False
def do_something(self):
i = 0
while not self.finished:
i+=1
print(i)
time.sleep(1)
def set_finished(self, finished_arg):
self.finished = finished_arg
def startThreadedMethod(self):
with concurrent.futures.ThreadPoolExecutor() as executor:
t1 = executor.submit(self.do_something)
test = TestClass()
test.startThreadedMethod()
time.sleep(5)
test.set_finished(True)

Python timer with threading

I wanted to create a simple timer script to use it with my telegram bot, but something doesn't work like I want it to. Here is the code:
#!/usr/bin/python
from threading import Timer
class Timer:
def __init__(self, router):
self.routes = [
("^/timer\s(?P<time>[^$]+)$", self.main),
]
def timer_end(self):
print 'Timer End'
def main(self, message, match):
Timer(5, self.timer_end, ()).start()
I always get this error:
TypeError: __init__() takes exactly 2 arguments (4 given)
It would be great if someone could help.
Thanks in advance!
As #swstephe mentioned in a comment:
You import Timer, then you create a class which overwrites Timer. Maybe you should just "import threading" then use "threading.Timer" to distinguish the two?

QTimer not executed when called inside Singleton/Borg

I've implemented a timer using QTimer inside a Singleton. The Singleton is implemented using the Borg pattern. If I start a QTimer with single shot inside a function of the Singleton it won't be executed. The same call in a function outside the Singleton works well.
This is the code:
#!/usr/bin/env python
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication
class Borg():
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
class Timers(Borg):
def __init__(self):
Borg.__init__(self)
def update_not_working(self):
QTimer().singleShot(2000, Timers().update_not_working)
print('update not working')
def update_working():
QTimer().singleShot(2000, update_working)
print('update working')
if __name__ == '__main__':
app = QApplication(sys.argv)
print('start timer')
Timers().update_not_working()
update_working()
sys.exit(app.exec_())
The output is (no error, no exception):
start timer
update not working
update working
update working
....
Why is one call working and the other not? Is there something wrong with my implementation of the Borg or with the usage of QTimer?
print self in update_not_working and print Timers() in update working show that the Timers object before the event loop started is different from the one within:
update not working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb52162cc>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
update working
<__main__.Timers instance at 0xb521650c>
#classmethod should help here because it allows to call the method on an instance OR on the class as you do in the single shot statement.
Compare: When should I use #classmethod and when def method(self)?
This is actually just a matter of normal garbage-collection.
If you add some debugging code to your example like this:
class Timers(Borg):
def __init__(self):
Borg.__init__(self)
print('init:', self)
def update_not_working(self):
QTimer().singleShot(1, Timers().update_not_working)
print('update not working')
def __del__(self):
print('deleted:', self)
it will produce output like this:
start timer
init: <__main__.Timers object at 0x7f194bf53eb8>
init: <__main__.Timers object at 0x7f1940cfdb00>
deleted: <__main__.Timers object at 0x7f1940cfdb00>
update not working
deleted: <__main__.Timers object at 0x7f194bf53eb8>
update working
update working
As you can see, both of the Timers instances get deleted long before the single-shot timer sends its timeout() signal. And when they deleted, their instance-methods get deleted as well, which will automatically disconnect them from the signal. This shows that the Borg pattern does not produce a true singleton: it just mimics some of the behaviour of one.
If you use a real singleton class, like this:
class Timers2(object):
_instance = None
def __new__(cls):
if Timers2._instance is None:
Timers2._instance = object.__new__(cls)
return Timers2._instance
def update_not_working(self):
QTimer().singleShot(2000, Timers2().update_not_working)
print('update not working')
your example will work as expected. This is because there is only ever one instance, and it is kept alive by being cached as a class attribute.
Finally, the reason why the update_working() succeeds, is because it is a globally defined function. As with the class attribute, this ensures that it won't get garbage-collected until the script completes.
class Borg():
_shared_state = {}
def __init__(self):
self.__dict__ = self._shared_state
class Timers(Borg):
def __init__(self):
Borg.__init__(self)
#classmethod
def update_not_working(cls):
QTimer().singleShot(2000, Timers().update_not_working)
print('update not working')
def update_working():
QTimer().singleShot(2000, update_working)
print('update working')
if __name__ == '__main__':
app = QApplication(sys.argv)
print('start timer')
Timers().update_not_working()
update_working()
sys.exit(app.exec_())

PyQt Code Splitting - Design Vs Functionality

Am struggling to comprehend how to split code in (Py)Qt. The aim is to have the design & navigation tabs in QMainWindow, each tab triggering code in other files. So far it only launches with the ActionClass in the same document / putting in an external document causes 'app not defined' when clicking the tab. The below works without errors, but is clunky.
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.u = Ui_MainWindow()
self.u.setupUi(self)
self.u.tabs.currentChanged.connect(self.TabsChanged)
def TabsChanged(self, i):
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
class ActionClass(Main):
def __init__(self):
app.u.lineEdit.setText("test")
app = Main()
app.show()
sys.exit(app.exec_())
The examples I keep seeing have all code in one document. Is there another way to do this e.g. where the ActionClass is in another file/writing u.lineEdit.setText instead of app.u.lineEdit.setText. It seems inheritance & an instance of Main can't be accessed from the ActionClasses doc, so I can't see how they would communicate back to the Main?
Much appreciated
As suggest #M4rtini you can separate your code into python modules. And then import them (use them) in your main module.
For instance the code you posted can be separated in to files:
# actions_class.py
class ActionClass(Main):
def __init__(self):
app.u.lineEdit.setText("test")
and
# main.py
from action_class import ActionClass # This line no need much explanation ;)
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.u = Ui_MainWindow()
self.u.setupUi(self)
self.u.tabs.currentChanged.connect(self.TabsChanged)
def TabsChanged(self, i):
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
app = Main()
app.show()
sys.exit(app.exec_())
In order to understand how import works see the link I left you above.
More explanation
Lest's see:
The correct way of executin code inside a __init__ method is creating an instance. See the example below.
class A:
def __init__(self):
print("Executing A.__init__")
print("Doing things wrong")
A.__init__ # This don't print enything
print("Doing things well")
A() # This works as expected.
So, you line reads:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
and should reads:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass()
On the other hand, is a bad practice put code that's not for initialize the instance inside the __init__ methods.
If you don't need the instance but yet you want to store the functions inside a class (something like a c++ namespace) you creating
use #staticmethod decorator.
class A:
#staticmethod
def foo():
print("Oh, wow, a static method in Python!")
A.foo()
So, your ActionClass could be rewritten as:
class ActionClass(Main):
#staticmethod
def do_action:
app.u.lineEdit.setText("test")
ans then you can use it like this:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.do_action()

Python and indentation, having trouble getting started.

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()

Categories