Re: Signals and Slots - Summerfield - what exactly is a signal?
On Sun, 6 Aug 2017 03:18 am, Michael Torrie wrote: > Forgive Steven for his off-topic reply. I assume he's trying to goad you > into having a more specific subject line. He knows darn well what PyQt, > even if he has no experience with it. Pardon me, I said: "I don't know what Qt signals are." I know what Qt is. I don't know what Qt signals are, just as I said. Well I do now, thanks to Veek answering his own question with a good explanation of Qt slots. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
On 08/05/2017 08:28 AM, veek wrote: > At a certain point beyond the general stuff, questions about PyQt might be better suited to the PyQt mailing list, hosted by the company that maintains PyQt: https://www.riverbankcomputing.com/mailman/listinfo/pyqt -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
On 08/05/2017 12:19 PM, Marko Rauhamaa wrote: > I would express it as just saying that the Qt developers appropriated > the word "signal" for what is simply a callback. I'd say a slot is a callback. A signal is the designation of something that will trigger callbacks. > Years back I took a brief loook at Qt. I had heard that one of their > great selling points was that they did C++. At the time, C++ was my > bread and butter, and I had been baffled at how bad C++ was at > expressing such a basic thing as callbacks. > > Turns out Qt didn't do callbacks using C++. Instead they specified a > sort of macro language to express callbacks and offered what was known > as a "metacompiler" that converted those macros into real C++. Off-topic, but probably still worth talking about, since the OP does appear interested in Qt internals and how they relate to Python. As for Qt not being really C++, that's only partially true these days. Qt code you write is actual C++, directly compile-able with any standards-compliant C++ compiler. moc, the metacompiler you're referring to, generates some helper code that is required to tie the Qt objects together. And you can argue this is only necessary because of deficiencies in C++ (at least pre-STL days). But this is no different or burdensome than requiring a step to compile an XML ui file to code like many/most UI toolkits do. The biggest problem with moc in my mind is that it hides the fact that signal emission is done by name in the Qt engine, using string lookups and comparisons. In your code they look like actual identifiers but moc generates string equivalents in the meta class code. This can lead to really weird bugs. It's been a long time since I ran into this problem so I can't remember the specifics. I'm not sure if this problem would manifest itself in Python code, but I suspect it might. > It was a big disappointment both with respect to C++ and Qt. > > Now, the Standard Template Library offered elaborate macros (aka functor > templates) that allowed you to express callbacks with zero, one or two > arguments (in a cumbersome way). Boost, a famous C++ class library, > added functor support to three, four, five, six, seven, eight, nine, > and--hear this!--TEN arguments. Yeah Qt has never used templates because they didn't exist when Qt was first started. Now I think you could use templates to do a lot of what moc does, and indeed Gtkmm uses templates to make a very nice, very native C++ binding for GTK+. I have had to, on occasion, make my own templates for gtkmm when the number of parameters I needed to bind was different than the prefab templates provided. Templates can be really cumbersome. One area that the template-based GTKmm really shone compared to Qt was that, in C++ at least, signatures between the signal and slot were checked at compile time, thanks to templates. In Qt, they end up being essentially bare function pointers (might get a runtime error? I can't remember). > All this nonsense because it hadn't occurred to Bjarne Stroustrup to > define so-called method pointers in a sane manner. It was left to > another Dane, Anders Hejlsberg, to demonstrate how they ought to have > been defined, namely, as delegates (as in Delphi and C#). Unfortunately, > it was too late for C++. > > Now, I'm hearing C++ supports proper closures: http://en.cppreference.com/w/cpp/language/lambda>. I wonder if Qt would > eventually migrate to them. > > At any rate, Python never had to come up with such tricks for callbacks. > Python's closure syntax is maybe the most natural there is. Too bad if > PyQt confuses Python programmers with "signals" and "slots" when they > are simply methods. True enough. When you work with PyQt, unfortunately these C++ details do leak through, which is the biggest weakness of PyQt (and also PySide). So I guess that's reason enough to be familiar with the warts. Despite the warts, PyQt is my go-to toolkit for doing the simple GUI stuff I need, as it is easy to install and run on any platform and looks great. I wrote a simple compatibility shim to let me use both PySide and PyQt4 with the same code. That way if I need to release code in a non-GPL way, I can just switch to PySide. PySide had its own issues because of how the bindings are made. One of them is that occasionally PySide drops a reference to a Qt C++ object, which can lead to a segfault. And I have no idea the state of PySide for Qt5. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
Le 05/08/17 à 16:28, veek a écrit : 1. What exactly is a signal. In hardware, an interrupt can be viewed as a signal and the voltage on a pin will suddenly jump to +5V as an indicator that an interrupt has occurred. With Qt signals - if a widget-c++ code has to 'signal' an event - what does it do? As a consequence of not understanding the above.. 2. How do you connect a single signal to multiple slots? Do the slots/methods get called one by one? or are they treated as independent threads and run on different cores? You have to connect yours slots each by each. self.my_button.clicked.connect(self.foo) self.my_button.clicked.connect(self.baz) ... Be care you can't know the order of the execution of foo and baz. Any thread will be created for that, the binding will be executed into the main loop of your app. But, if your signal is emitted from a thread, the slot will be executed into the main thread, this is a great advantage, your slot can interact safely with the graphics part of your app. 3. pg 130 of Summerfield class ZeroSpinBox(QObject): def __init__(self, parent=None): super(...blah initialize QObject with parent self.connect(self, SIGNAL("valuedChanged(int)"), self.checkzero) def checkzero(self): if self.value() == 0: self.emit(SIGNAL("atzero"), self.zeros) basically when SpinBox gets set to zero we emit 'atzero' and return a zeros counter. What i don't get is the valueChanged(int) bit.. he clearly defines an (int) being passed to checkzero so shouldn't the definition reflect the same? Mistake? This is the old signal-slot methods, I encourage you to use the new (new but not recent) method Like this: from QtCore import pyqtSignal class ZeroSpinBox(QObject): atZero = pyqtSignal(int) def __init__(self, parent=None): super(...blah initialize QObject with parent self.valuedChanged.connect(self.checkzero) def checkzero(self, value): if not value: # maybe increment self.zeros ? self.atzero.emit(self.zeros) A. additionally I did not understand short circuit signals where you can drop the (type1, type2) in the signature and just do SIGNAL("atzero") Is this doable ONLY in emit() or also in connect()?? I don't know, never used this construction of code. 4. pg 131 'any data can be passed as arguments to the emit method and they can be passed as Python objects' self.emit(SIGNAL("atzero"), 10, 20, 30) or self.emit(SIGNAL("atzero"), [10, 20, 30]) does he mean i can pass a SINGLE OBJECT of any python type or does he mean multiple independent containers? (assuming the definition matches) When you define your signal you can use any Python type sig = pyqtSignal(int, float, str, str, ...) 5. He says 'a signal with one argument is a Qt signal or a non-short-circuit Python signal' So if I have a Qt widget in C++ and it emits a valueChanged(int) signal.. okay he's going to have to convert our asm/x86 int to python-integer and then call the python-method that was mapped to 'valueChanged' with the python-integer argument OR the signal is being generated from Python code itself AND WILL be converted to C++ datatype - huh why?? The wrapper use simply the CPython "PyLong_AsLong" or "PyUnicode_FromString" or "Py_BuildValue" or other and you get always a Python object. I'm guessing there's some dispatch code that maintains a mapping table?? SO why can't it differentiate between inhouse python widget and Qt-c++ widget?? 6. "If we use the SIGNAL() function with a signalSignature (a possibly empty parenthesized list of comma-separated PyQt types)..."?? how can it be an empty () list..?? If there's a list it's no longer empty.. 7. What exactly is a Python signal vs a Qt signal originating from a C++- asm-widget?? PyQt is a wrapper around C++Qt so.. where are the python widgets?? 8. class TaxRate(QObject): def __init__(self): super(TaxRate, self).__init__() self.__rate = 17.5 def rate(self): return self.__rate def setRate(self, rate): if rate != self.__rate: self.__rate = rate self.emit(SIGNAL("rateChanged"), self.__rate) def rateChanged(value): print "TaxRate changed to %.2f%%" % value vat = TaxRate() vat.connect(vat, SIGNAL("rateChanged"), rateChanged) vat.setRate(17.5) # No change will occur (new rate is the same) vat.setRate(8.5) # A change will occur (new rate is different) Isn't this a mistake? self.connect( should be: vat.connect(vat, SIGNAL("rateChanged"), rate) Again, use the new syntaxe (new but not recent) it's more clear. Vincent -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
Michael Torrie: > Basically a signal emission is a call to the main loop that indicates > that an event has occurred, and then the main loop sees if there are > any registered callbacks that want to be notified of this event, and > if so it calls them, letting them execute. This is how event-driven > programming works. The concept of signals and slots is very similar to > explicit registering of callbacks in function. It differs only in > form. I would express it as just saying that the Qt developers appropriated the word "signal" for what is simply a callback. Years back I took a brief loook at Qt. I had heard that one of their great selling points was that they did C++. At the time, C++ was my bread and butter, and I had been baffled at how bad C++ was at expressing such a basic thing as callbacks. Turns out Qt didn't do callbacks using C++. Instead they specified a sort of macro language to express callbacks and offered what was known as a "metacompiler" that converted those macros into real C++. It was a big disappointment both with respect to C++ and Qt. Now, the Standard Template Library offered elaborate macros (aka functor templates) that allowed you to express callbacks with zero, one or two arguments (in a cumbersome way). Boost, a famous C++ class library, added functor support to three, four, five, six, seven, eight, nine, and--hear this!--TEN arguments. All this nonsense because it hadn't occurred to Bjarne Stroustrup to define so-called method pointers in a sane manner. It was left to another Dane, Anders Hejlsberg, to demonstrate how they ought to have been defined, namely, as delegates (as in Delphi and C#). Unfortunately, it was too late for C++. Now, I'm hearing C++ supports proper closures: http://en.cppreference.com/w/cpp/language/lambda>. I wonder if Qt would eventually migrate to them. At any rate, Python never had to come up with such tricks for callbacks. Python's closure syntax is maybe the most natural there is. Too bad if PyQt confuses Python programmers with "signals" and "slots" when they are simply methods. Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
Forgive Steven for his off-topic reply. I assume he's trying to goad you into having a more specific subject line. He knows darn well what PyQt, even if he has no experience with it. And of course, as always you will want to post a complete, working example that we can see and comment on, rather than extracts of the code. It's much harder to comment on that. On 08/05/2017 08:28 AM, veek wrote: > 1. What exactly is a signal. In hardware, an interrupt can be viewed as a > signal and the voltage on a pin will suddenly jump to +5V as an indicator > that an interrupt has occurred. With Qt signals - if a widget-c++ code has > to 'signal' an event - what does it do? Basically a signal emission is a call to the main loop that indicates that an event has occurred, and then the main loop sees if there are any registered callbacks that want to be notified of this event, and if so it calls them, letting them execute. This is how event-driven programming works. The concept of signals and slots is very similar to explicit registering of callbacks in function. It differs only in form. So it sounds from your post that the book you are following is older and uses some of the older forms for signals and slots in PyQt. In recent years, PyQt has made some things nicer, make making signals just be members of the class that you can access through python as if they were a member of the instance. so my code in response to your questions will reflect this newer style. I recommend you look at the various online tutorials for PyQt (I still am using PyQt4, but PyQt5 will be nearly the same). > As a consequence of not understanding the above.. > > 2. How do you connect a single signal to multiple slots? Do the > slots/methods get called one by one? or are they treated as independent > threads and run on different cores? You simply have more than one connect() call. for example: button1.clicked.connect(callback1) button1.clicked.connect(callback2) Both callbacks will run when button1 emits its "clicked" signal. Then the callbacks are executed in some kind of order when the signal is emitted, one at a time. GUIs are typically single-threaded. That's why it's important to not have long-running code in a callback. If you do need to do something in a call back that takes a while, you could spawn a thread and turn the work over to a thread, and then return control of the GUI thread back to the main loop. > > 3. pg 130 of Summerfield > > class ZeroSpinBox(QObject): I'm guessing that should be QSpinBox, not QObject, as this class is just adding behavior to the spinbox. If the book really has it as QObject, I would suspect it is a mistake. But without seeing the entire example program, I cannot say. >def __init__(self, parent=None): > super(...blah initialize QObject with parent > self.connect(self, SIGNAL("valuedChanged(int)"), self.checkzero) > >def checkzero(self): > if self.value() == 0: > self.emit(SIGNAL("atzero"), self.zeros) > > basically when SpinBox gets set to zero we emit 'atzero' and return a zeros > counter. > > What i don't get is the valueChanged(int) bit.. he clearly defines an (int) > being passed to checkzero so shouldn't the definition reflect the same? > Mistake? Normally it should match the signature, yes. Whether this is a mistake, I don't know. I believe PyQt could be ignoring the parameters the slot callback doesn't have defined. And since he's calling self.value() to read the actual value, he doesn't really need the int parameter, though if it were me I'd use the parameter and not call self.value() at all. > A. additionally I did not understand short circuit signals where you can > drop the (type1, type2) in the signature and just do > SIGNAL("atzero") > > Is this doable ONLY in emit() or also in connect()?? As far as I know, only in the emit(). I'm not familiar with this "short circuit" thing. In fact I've never heard of it and have done a few things in PyQt. For defining signals, PyQt has defined a new method for creating signals that's much cleaner than using the SIGNAL() call: class ZeroSpinBox(QSpinbox): atzero = PyQt4.pyqtSignal() #could list arguments here if desired someother = PyQt4.pyqtSignal('int','bool') ... def checkzero(self, value): if value == 0: self.atzero.emit() Note that parameters to pyqtSignal can be either Python types that PyQt can marshall (int, float,str, any QObject-derived class etc), or C++ types as a name in a string. > 4. pg 131 'any data can be passed as arguments to the emit method and they > can be passed as Python objects' > > self.emit(SIGNAL("atzero"), 10, 20, 30) or > self.emit(SIGNAL("atzero"), [10, 20, 30]) > does he mean i can pass a SINGLE OBJECT of any python type or does he mean > multiple independent containers? > (assuming the definition matches) You can pass any number of extra parameters when emitting a signal. I've
Re: Signals and Slots - Summerfield - what exactly is a signal?
Steve D'Aprano wrote: > On Sun, 6 Aug 2017 12:28 am, veek wrote: > >> 1. What exactly is a signal. In hardware, an interrupt can be viewed as a >> signal and the voltage on a pin will suddenly jump to +5V as an indicator >> that an interrupt has occurred. With Qt signals - if a widget-c++ code >> has to 'signal' an event - what does it do? > > I don't know what Qt signals are. > > Unix signals are an interrupt mechanism used by Unix and Linux operating > systems. Windows may support them as well. The "kill" system command sends > signals to a specific running process, which will then jump to a specific > piece of code. The command is called "kill" because the main use for this > is to terminate processes. > > Python supports these signals: > > https://docs.python.org/3/library/signal.html > > https://pymotw.com/3/signal/index.html > > > >> As a consequence of not understanding the above.. >> >> 2. How do you connect a single signal to multiple slots? Do the >> slots/methods get called one by one? or are they treated as independent >> threads and run on different cores? > > What are slots? > > >> 3. pg 130 of Summerfield > > What is Summerfield? > > > The book I'm reading is: Mark Summerfield - Rapid GUI Programming with Python and Qt. PyQt is a wrapper around the C++/Qt library and they have a Signal and Slot mechanism for doing GUI/event-driven work - Qt doesn't have it. Basically if you have a widget like QSpinBox it'll be rendered/drawn using a C++ Qt library (which is fast). Anyway, widgets support 'events' like mouse-over and click and they are constantly generating events which are mostly ignored by the PyQt library and discarded. However if you decide you want to handle an event then you use PyQt's signal/slot mechanism: slot's a method and signal looks to be basically a string. Eg: class Form(QWidget): def __init__(self, parent=None): super(Form, self).__init__(parent) #init QWidget with parent is set combo = QComboBox() self.connect(combo, SIGNAL("some_event(int)"),self.combo_event_handler) def combo_event_handler(self, i): pass combo_event_handler's the slot.. it's just a python OR Qt method. QComboBox() will result in a combo box being drawn when the app is started via app = QApplication() app.exec_() then if I mouse over the widget it'll generate an 'event'/'signal' and call the handler to process - event driven programming "some_event()" is a string being passed to connect() and that's a function signature that tells connect what types the handler expects. combo_event_handler can be a Qt method in which case conversion occurs to C++ data types but it can also be a python method and if you short ckt then no conversion to C++ types occurs. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Slots - Summerfield - what exactly is a signal?
On Sun, 6 Aug 2017 12:28 am, veek wrote: > 1. What exactly is a signal. In hardware, an interrupt can be viewed as a > signal and the voltage on a pin will suddenly jump to +5V as an indicator > that an interrupt has occurred. With Qt signals - if a widget-c++ code has > to 'signal' an event - what does it do? I don't know what Qt signals are. Unix signals are an interrupt mechanism used by Unix and Linux operating systems. Windows may support them as well. The "kill" system command sends signals to a specific running process, which will then jump to a specific piece of code. The command is called "kill" because the main use for this is to terminate processes. Python supports these signals: https://docs.python.org/3/library/signal.html https://pymotw.com/3/signal/index.html > As a consequence of not understanding the above.. > > 2. How do you connect a single signal to multiple slots? Do the > slots/methods get called one by one? or are they treated as independent > threads and run on different cores? What are slots? > 3. pg 130 of Summerfield What is Summerfield? -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Threads in Python 3.5 or so
On Mon, Oct 10, 2016 at 12:05 AM, dieterwrote: > Dan Stromberg writes: >> I have a program http://stromberg.dnsalias.org/~dstromberg/looper/ >> that I use and maintain. >> >> It's like GNU parallel or similar - yet another "run n processes, m at >> a time" implementation. Interestingly, I've only used/tested it on >> Linux, but it's under a Microsoft copyright because Microsoft acquired >> a Linux company I was working for. >> >> Anyway, it seems to work well, except one annoying bug. >> >> That bug is: if you control-C the top-level process, all the >> subprocesses are left running. >> >> I've been thinking about making it catch SIGINT, SIGTERM and SIGHUP, >> and having it SIGKILL its active subprocesses upon receiving one of >> these signals. >> >> However, it's multithreaded, and I've heard that in CPython, threads >> and signals don't mix well. > > I would not state it this way. > > Signals are delivered to processes (not process threads). > That leads to the question which thread (in a multi thread application) > will handle a signal when it arrives. > In Python, the design decision has been not to use the currently > running thread (which may not be a Python thread at all or > may have executed Python code but at the moment runs C code outside > of Python) but let the signal be handled deterministically by > the main thread (once it starts again to execute Python code). > This looks like a sane decision to me. Thank you for the clear explanation. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Threads in Python 3.5 or so
Dan Strombergwrites: > I have a program http://stromberg.dnsalias.org/~dstromberg/looper/ > that I use and maintain. > > It's like GNU parallel or similar - yet another "run n processes, m at > a time" implementation. Interestingly, I've only used/tested it on > Linux, but it's under a Microsoft copyright because Microsoft acquired > a Linux company I was working for. > > Anyway, it seems to work well, except one annoying bug. > > That bug is: if you control-C the top-level process, all the > subprocesses are left running. > > I've been thinking about making it catch SIGINT, SIGTERM and SIGHUP, > and having it SIGKILL its active subprocesses upon receiving one of > these signals. > > However, it's multithreaded, and I've heard that in CPython, threads > and signals don't mix well. I would not state it this way. Signals are delivered to processes (not process threads). That leads to the question which thread (in a multi thread application) will handle a signal when it arrives. In Python, the design decision has been not to use the currently running thread (which may not be a Python thread at all or may have executed Python code but at the moment runs C code outside of Python) but let the signal be handled deterministically by the main thread (once it starts again to execute Python code). This looks like a sane decision to me. Your problem description indicates that the problem is not with signal handling by threads but with signal delivery by the operating system. In Linux, SIGINT signals in response to a "CTRL-C" are delivered to the process group of the "control terminal". Thus, with appropriate Linux calls, you can control whether or not such a SIGINT is delivered to a subprocess. Other operating systems may not provide such a control or it may need different (OS dependent) calls. -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Threads in Python 3.5 or so
Dan Stromberg: > That bug is: if you control-C the top-level process, all the > subprocesses are left running. Sorry, don't have a solution for your particular Python situation. > I've been thinking about making it catch SIGINT, SIGTERM and SIGHUP, > and having it SIGKILL its active subprocesses upon receiving one of > these signals. SIGKILL is probably a bad idea. It doesn't give the subprocess any opportunity for a graceful exit. For example, Python's try/finally blocks will fail to work as advertised. Better use a catchable signal. > However, it's multithreaded, and I've heard that in CPython, threads > and signals don't mix well. Python does confuse matters, but both threads and signals are problematic entities under Linux. You need to be very well versed in the semantics of both operating system concepts (man 7 pthreads, man 7 signal). Marko -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Threads in Python 3.5 or so
Dan Strombergwrites: > That bug is: if you control-C the top-level process, all the > subprocesses are left running. Are you setting the daemon flag? -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals and Threads in Python 3.5 or so
On Mon, Oct 10, 2016 at 10:52 AM, Dan Strombergwrote: > That bug is: if you control-C the top-level process, all the > subprocesses are left running. > > I've been thinking about making it catch SIGINT, SIGTERM and SIGHUP, > and having it SIGKILL its active subprocesses upon receiving one of > these signals. > > However, it's multithreaded, and I've heard that in CPython, threads > and signals don't mix well. Generally, expect SIGINT to be handled by the main thread, and code accordingly. But I've never used the low-level thread and _thread modules, so I'd be inclined to follow through with the TODO and make it use threading instead. This simple example appears to work fine on my system (Debian Stretch, Linux 4.6, amd64), but I can't make any hard-and-fast guarantees. import threading import signal import random import time halt = False def thread(): global halt try: print(threading.current_thread(), "-- start") for i in range(random.randrange(10, 20)): time.sleep(1) if halt: break print(threading.current_thread(), "--", i) except KeyboardInterrupt: print(threading.current_thread(), "-- SIGINT") halt = True print(threading.current_thread(), "-- end") for i in range(5): threading.Thread(target=thread).start() thread() Hit Ctrl-C and all threads will quickly terminate. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Signals/Slots support in Python
On 5/1/08, Brian Vanderburg II ([EMAIL PROTECTED]) wrote: I don't know if any such support is already built in, so I ended up making my own simple signals/slots like mechanism. If anyone is interested then here it is, along with a simple test. It can connect to normal functions as well as instance methods. It also supports weak connections where when an object is gone, the slot is gone as well, the slot just holds a weak reference to the object. Did you review this? http://pydispatcher.sourceforge.net/ from what I understand is originally based upon this: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/87056 and subsequently integrated into this: http://djangoproject.com - # Begin Signal import weakref import random class Signal: class Slot: def __init__(self, fn): self.__fn = fn def __call__(self, accum, *args, **kwargs): result = self.__fn(*args, **kwargs) return accum(result) class WeakSlot: def __init__(self, conn, parent, fn, obj): self.__conn = conn # Avoid circular references so deleting a signal will # allow deletion of the signal since the slot doesn't ref # back to it but only weakefs back to it self.__parent = weakref.ref(parent) self.__fn = fn self.__obj = weakref.ref(obj, self.Cleanup) def __call__(self, accum, *args, **kwargs): obj = self.__obj() if obj is None: return True result = self.__fn(obj, *args, **kwargs) return accum(result) def Cleanup(self, ref): parent = self.__parent() if parent is not None: parent.Disconnect(self.__conn) class Accumulator: def __call__(self, *args, **kwargs): return True def Finalize(self): return None def __init__(self): self.__slots = [ ] # This connects a signal to a slot, but stores a strong reference so # The object will not be deleted as long as the signal is connected def Connect(self, fn): conn = self.NewConn() self.__slots.append([conn, Signal.Slot(fn)]) return conn # This connects a signal to a slot, but store a weak reference so # when the object is gone the slot will not be called. Because of # the implemenations, it is not possible to do WeakConnect(obj.Fn), # since obj.Fn is a new object and would go to 0 refcount soon after # the call to WeakConnect completes. Instead we must do a call as # WeakConnect(ObjClass.Fn, obj) # Only the object is weak-referenced. The function object is still # a normal reference, this ensures that as long as the object exists # the function will also exist. When the object dies, the slot will # be removed def WeakConnect(self, fn, obj): conn = self.NewConn() self.__slots.append([conn, Signal.WeakSlot(conn, self, fn, obj)]) return conn # Disconnect a slot def Disconnect(self, conn): result = self.Find(conn) if result = 0: del self.__slots[result] # Disconnect all slots def DisconnectAll(self): self.__slots = [ ] # Create an accumulator. Accumulator will be called as a callable # for each return value of the executed slots. Execution of slots # continues as long as the reutrn value of the accumulator call is # True. The 'Finalize'function will be called to get the result # A custom accumulator can be created by deriving from Signal and # Creating a custom 'Accumulator' class, or by deriving from Singal # and creating CreateAccumulator def CreateAccumulator(self): return self.Accumulator() # Execute the slots def __call__(self, *args, **kwargs): accum = self.CreateAccumulator() for conn in xrange(len(self.__slots)): if not self.__slots[conn][1](accum, *args, **kwargs): break return accum.Finalize() # Create a connection name def NewConn(self): value = 0 while self.Find(value) = 0: value = random.randint(1, 1) return value def Find(self, conn): for i in xrange(len(self.__slots)): if self.__slots[i][0] == conn: return i return -1 # End Signal def fn1(): print Hello World def fn2(): print Goodbye Space class O: def __init__(self, value): self.value = value def Action(self): print O %d % self.value a = Signal() a.Connect(fn1) a.Connect(fn2) print Part 1 a() a.DisconnectAll() o1 = O(4) o2 = O(12) a.WeakConnect(O.Action, o1) a.Connect(o2.Action) print Part 2 a() print Part 3 o1 = None a()
Re: Signals/Slots support in Python
On Thu, 01 May 2008 08:44:27 -0600, Scott SA wrote: Did you review this? http://pydispatcher.sourceforge.net/ from what I understand is originally based upon this: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/87056 and subsequently integrated into this: http://djangoproject.com AFAIK PyDispatcher evolved into Louie project [1]. Louie has more features, but dispatch module inside Django is dramatically faster and is going to be even faster. [1] http://pylouie.org/ -- Ivan -- http://mail.python.org/mailman/listinfo/python-list
Re: Signals
On Wed, 2007-04-18 at 08:39 +0100, Robert Rawlins - Think Blue wrote: Hello Chaps, I posted about this the other day but I’m still struggling to get any form of result from it. Basically I have the following piece of code, and according to its API is produces singals when particular events occur, but i have no idea how to list for events, I’ve tried all sorts of combinations using the signal module but haven’t been able to get it working. [...] import dbus, signal [...] Now here is a copy of the API documentation that lists the signals thrown by the API, this is the one I’m trying to listen for. void RemoteDeviceFound(string address, uint32 class, int16 rssi) This signal will be send every time an inquiry result has been found by the service daemon. In general they only appear during a device discovery. Basically I’m just looking to run a function that will print those details to screen. Can anyone help with working out how to listen for this signal? The signal module is for handling process signals the operating system sends to your python process. The API you're using (dbus, a crucial detail you neglected to mention before) doesn't send this kind of signal. Googling for 'python dbus documentation' brings up http://dbus.freedesktop.org/doc/dbus-python/api/ , which seems to explain everything you need. You need to get an instance of dbus.Interface, which you seem to have done, and call its connect_to_signal() method, which you don't seem to have done. I’d also like to know how i can keep the application running until I decided to stop it manually, as the DiscoverDevices() can take a while to complete and send out several RemoteDeviceFound() signals in that period. The very first section of the above mentioned documentation talks about needing a main loop for receiving signals, and it provides example boilerplate code for how to set up a main loop. Hope this helps, Carsten. -- http://mail.python.org/mailman/listinfo/python-list
RE: Signals
Thanks Carsten, Sorry for not mentioning the dbus before, I thought that the signals were a general python thing, I didn’t realize it was a specific dbus thing. I've now modified the code so it looks like this. #!/usr/bin/python import dbus from gobject import MainLoop, idle_add from dbus.mainloop.glib import DBusGMainLoop def main_function(): bus = dbus.SystemBus() manager = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'),'org.bluez.Manager') adapter = dbus.Interface(bus.get_object('org.bluez', manager.DefaultAdapter()),'org.bluez.Adapter') def remote_device_found(addr, class_, rssi): print 'Found:', addr adapter.connect_to_signal('RemoteDeviceFound', remote_device_found) adapter.DiscoverDevices() if __name__ == '__main__': idle_add(main_function) dbus_mainloop_wrapper = DBusGMainLoop(set_as_default=True) mainloop = MainLoop() mainloop.run() Which should implement the main loop and keep the application alive, however when running the program I get the following error thrown at me. File ./scan4.py, line 5, in ? from dbus.mainloop.glib import DBusGMainLoop ImportError: No module named mainloop.glib Any ideas what might be causing this? My guess is that I don’t have one of the dependency installed properly, but I have no idea which ones I need. Thanks for any more help you can offer, its greatly appreciated. Rob -Original Message- From: Carsten Haese [mailto:[EMAIL PROTECTED] Sent: 18 April 2007 13:43 To: Robert Rawlins - Think Blue Cc: python-list@python.org Subject: Re: Signals On Wed, 2007-04-18 at 08:39 +0100, Robert Rawlins - Think Blue wrote: Hello Chaps, I posted about this the other day but I’m still struggling to get any form of result from it. Basically I have the following piece of code, and according to its API is produces singals when particular events occur, but i have no idea how to list for events, I’ve tried all sorts of combinations using the signal module but haven’t been able to get it working. [...] import dbus, signal [...] Now here is a copy of the API documentation that lists the signals thrown by the API, this is the one I’m trying to listen for. void RemoteDeviceFound(string address, uint32 class, int16 rssi) This signal will be send every time an inquiry result has been found by the service daemon. In general they only appear during a device discovery. Basically I’m just looking to run a function that will print those details to screen. Can anyone help with working out how to listen for this signal? The signal module is for handling process signals the operating system sends to your python process. The API you're using (dbus, a crucial detail you neglected to mention before) doesn't send this kind of signal. Googling for 'python dbus documentation' brings up http://dbus.freedesktop.org/doc/dbus-python/api/ , which seems to explain everything you need. You need to get an instance of dbus.Interface, which you seem to have done, and call its connect_to_signal() method, which you don't seem to have done. I’d also like to know how i can keep the application running until I decided to stop it manually, as the DiscoverDevices() can take a while to complete and send out several RemoteDeviceFound() signals in that period. The very first section of the above mentioned documentation talks about needing a main loop for receiving signals, and it provides example boilerplate code for how to set up a main loop. Hope this helps, Carsten. -- http://mail.python.org/mailman/listinfo/python-list
Re: Signals and threads again
On Fri, 13 Oct 2006 11:37:46 -0700 Mitko Haralanov [EMAIL PROTECTED] wrote: The problem that I am experiencing is that when SIGINT is sent to the program, it gets delivered to the child processes (the fork'ed ones) but the main thread's signal handler is never invoked. I know that Python masks signals in threads but they should be fine in the main thread and that is where they should get delivered. OK. I did an experiment where instead of creating a spinning thread, I just call that function. Now, the signal gets delivered to the main program thread but it sill get delivered to the child processes, as well. Why are those signals going there?? It's driving me crazy! -- Mitko Haralanov [EMAIL PROTECTED] Senior Software Engineer 650.934.8064 System Interconnect Group http://www.qlogic.com -- http://mail.python.org/mailman/listinfo/python-list
Re: signals (again)
I found a good solution to this problem in Richard Steven's _Network_Programming_. It seems like everything shows up in Steven's books! Rather than pausing, you do a blocking read on a pipe. You only write to the pipe from within the signal handler. However, this brings up the better question: why was 'pause' ever implemented? No matter what you do, the signal that you expect to wake you up may occur immediately prior to the pause, and you'll miss it. Starting that question in a new thread. -- http://mail.python.org/mailman/listinfo/python-list
Re: signals (again)
How does that help? I interpret use asynchronous calls to mean use fcntl to set an FN_NOTIFY on the directory in order to be alerted when something needs to be done. But the method of doing that which I outlined above has a critical section in which the incoming signal will not be noticed. All of the solutions I can think of for getting around it involve a lot of acrobatics that I'm fairly certain aren't necessary, and more to the point I don't think they actually solve the problem. There is always a section in which the signal arrives just before the pause, so it doesn't wake us up out of the pause as it is intended to. We can set globals in the signal handler, and then check them right before the pause, but if they get set after we check, then we're hosed. I was hoping that perhaps the following code might be atomic: if notify_occurred or signal.pause(): but I'm almost certain that it's not. The problem is localized, so I don't see how invoking a seperate thread is useful. Could you elaborate on how you think that will help? -- http://mail.python.org/mailman/listinfo/python-list
Re: signals (again)
bill [EMAIL PROTECTED] writes: I see this (or similar) question occasionally looking back through the archive, but haven't yet seen a definitive answer, so I'm going to ask it again. Consider the following: while True: do_something_to_files_in_directory(fd) fcntl(fd, F_NOTFIY, DN_CREATE) signal.pause() How do you deal with the signal that occurs after the fcntl and before the pause? I don't think you can, sorry. Cheers, mwh -- Get out your salt shakers folks, this one's going to take more than one grain. -- Ator in an Ars Technica news item -- http://mail.python.org/mailman/listinfo/python-list
Re: signals (again)
bill [EMAIL PROTECTED] writes: What's the pythonic thing to do here? How can I guarantee timely response to the creation of a file in the directory referenced by fd? Use asynchronous calls and/or a separate thread. -- http://mail.python.org/mailman/listinfo/python-list
Re: Signals and system
# [EMAIL PROTECTED] / 2005-04-10 20:55:05 +1000: Hi folks, My python program needs to download a number of files. Each file comes as a list of mirrors of that file. Currently, I am using system (os.system) to run wget. The mechanism is in a loop, so that it will try all the mirrors while wget is exiting with a non-zero exit status. This is working fine as long as the user feels there is no need to interrupt it. If wget receives a SIGINT, it stops (as expected) and returns non-zero (1 from memory). The call to system returns the same status code, indicating that wget failed, but the program has no knowledge that it was a signal the killed wget, rather than a failed download, and as such it tries the next mirror. I would like to be notified if wget received any signals, so that the user doesn't need to repetitively press Ctrl-C for each and every mirror to get the downloading process to stop. Can someone point me in the right direction? http://docs.python.org/lib/os-process.html#l2h-1682 On Unix, the return value is the exit status of the process encoded in the format specified for wait(). http://docs.python.org/lib/os-process.html#l2h-1684 return a tuple containing its pid and exit status indication: a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 -- http://mail.python.org/mailman/listinfo/python-list