James wrote:
> Given this explanation, it's probably not a great idea to use  
> signal.signal() then.  ;)

In this case, it seems to me that setting the SIG_DFL action for SIGPIPE
is precisely what one would want to do.

This is pure speculation, but if you were to re-implement some of the
subprocess module functionality for a similar task (using the os module
methods for processes and pipes), you could wrap the appropriate calls
in a try/except to trap a broken pipe. IIUC, this is exactly the reason
python sets SIGPIPE signals to SIG_IGN (see the signal module docs:
http://docs.python.org/lib/module-signal.html). A casual attempt appears
to reveal that the subprocess module swallows these exceptions. I hope
I'm wrong, because I tend to think that trapping with a try/except would
be the preferred approach to this problem. Perhaps someone can confirm,
or help to clarify?

My previous signal example was a bit careless. I agree with Alan, it's
seems best to exercise some caution when messing with signals. It may be
safer to restrict the sigpipe signal changes to processes only when you
need to.

Fortunately, you can accomplish this by passing a function as the
preexec_fn argument to subprocess 'call', 'Popen', and perhaps others.

Consider the following (credit to Matthew Woodcraft, posted to the
python-dev list in Jul 2007):

import signal
import subprocess as sp

def permit_sigpipe():
    signal.signal(signal.SIGPIPE, signal.SIG_DFL)

# no broken pipe, preexec_fn is called inside the child process
# thus setting sigpipe/sig_dfl for this process only
sp.call("yes 'Spam' | head -n 10", shell=True,
        preexec_fn=permit_sigpipe)

# oops, we should get a broken pipe message
sp.call("yes 'Spam' | head -n 10", shell=True)

> 
> Any other thoughts?  I've tried about redirecting my output using  
> subprocess.Popen( ... , stdout=*something* ), but I haven't had much  
> luck.  The error still appears.  Or should I be redirecting the  
> "stderr" instead of "stdout"?

yes :) but only stderr of the 'yes' command. If the 'make oldconfig'
command writes to stderr I presume you want to see it.

>
> Any ideas on how to use subprocess.Popen() to make this lovely little
> error disappear?
>

Use two Popen objects, redirect stderr from the left-side process
('yes') to /dev/null (or a log file, if you want to inspect), and
connect stdin of right-side process ('make oldconfig') to stdout of the
left-side by way of a subprocess.PIPE. Here's an example:

import subprocess as sp
# replace /dev/null below to a path of your choosing
# to send stderr to a file for later review
leftside = sp.Popen("yes ''", shell=True, stdout=sp.PIPE,
                 stderr=file('/dev/null', 'w'))
rightside = sp.Popen('make oldconfig', shell=True,
                 stdin=leftside.stdout)


IMHO, I think this approach is 'ok' for your purposes, since you are
unlikely to care about most stderr messages from 'yes'. However, I
wouldn't recommend it as a general practice.

Also beware, if you do this ...

import subprocess as sp
sp.call("yes '' | make oldconfig", shell=True,
                 stderr=file('/dev/null', 'w'))


... stderr from 'make oldconfig' will be sent to /dev/null as well.

HTH,
Marty


> Thanks!
> .james
> 
> On Oct 20, 2007, at 7:34 PM, Alan Gauld wrote:
> 
>> "James" <[EMAIL PROTECTED]> wrote
>>
>>> signal.signal(signal.SIGPIPE, signal.SIG_DFL)
>>>
>>> Before the snippet of code I included in my original e-mail
>>> (subprocess.call( "yes '' | make oldconfig" , shell=True )) got rid
>>> of the error.  I can't seem to figure out precisely what the
>>> signal.signal() function does (as shown above).
>> A signal is basically an interrupt. Its raised by the OS.
>> signal.signal catches the named signal(s) and handles it.
>> The default handler appears to just swallow the signal
>> silently.
>>
>> Its a bit like, in Python, doing
>>
>> try: someFunc()
>> except SomeError: pass
>>
>> The except clause catches the error but ignores it.
>>
>> signal.signal is doing much the same but at the OS level.
>>
>> My personal approach is to avoid using signal to trap
>> and ignore signals since they can be needed by other
>> processes running concurrently on the machine,
>> but in this case it appears harmless. But in general,
>> any approach which could interfere in unpredicable
>> ways with other processes on the computer is a
>> risky strategy IMHO.
>>
>> HTH,
>>
>> Alan G.
_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to