Re: Signals and Slots - Summerfield - what exactly is a signal?

2017-08-05 Thread Steve D'Aprano
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?

2017-08-05 Thread Michael Torrie
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?

2017-08-05 Thread Michael Torrie
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?

2017-08-05 Thread Vincent Vande Vyvre

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?

2017-08-05 Thread Marko Rauhamaa
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?

2017-08-05 Thread Michael Torrie
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?

2017-08-05 Thread veek
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?

2017-08-05 Thread Steve D'Aprano
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

2016-10-24 Thread Dan Stromberg
On Mon, Oct 10, 2016 at 12:05 AM, dieter  wrote:
> 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

2016-10-10 Thread dieter
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.


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

2016-10-10 Thread Marko Rauhamaa
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

2016-10-09 Thread Paul Rubin
Dan Stromberg  writes:
> 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

2016-10-09 Thread Chris Angelico
On Mon, Oct 10, 2016 at 10:52 AM, Dan Stromberg  wrote:
> 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

2008-05-01 Thread Scott SA
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

2008-05-01 Thread Ivan Illarionov
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

2007-04-18 Thread Carsten Haese
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

2007-04-18 Thread Robert Rawlins - Think Blue
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

2006-10-13 Thread Mitko Haralanov
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)

2005-08-12 Thread bill
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)

2005-08-11 Thread bill
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)

2005-08-11 Thread Michael Hudson
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)

2005-08-10 Thread Paul Rubin
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

2005-04-10 Thread Roman Neuhauser
# [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