[ python-Bugs-1220113 ] subprocess call() helper should close stdin if PIPE

SourceForge.net noreply at sourceforge.net
Wed Jun 22 10:45:21 CEST 2005


Bugs item #1220113, was opened at 2005-06-14 07:04
Message generated for change (Comment added) made by astrand
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1220113&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
Status: Closed
Resolution: Rejected
Priority: 5
Submitted By: Stuart Bishop (zenzen)
Assigned to: Peter Åstrand (astrand)
Summary: subprocess call() helper should close stdin if PIPE

Initial Comment:
The following code snippet should die instead of hang.

>>> from subprocess import call, PIPE
>>> rv = call(['/usr/bin/bzip2', '-c'], stdout=PIPE,
stdin=PIPE)

It makes no sense not to close stdin if it is PIPE
because the stream cannot be accessed.

The use case for this is ensuring a subprocess that
detects if it is connected to a terminal or not runs in
'batch' mode, and that it will die instead of hang if
it unexpectidly attempts to read from stdin.

Workaround is to use Popen instead.

----------------------------------------------------------------------

>Comment By: Peter Åstrand (astrand)
Date: 2005-06-22 10:45

Message:
Logged In: YES 
user_id=344921

>Wanting to pass a closed file handle is common. 

This is not my experience. 

>It is needed when calling a program that behaves
differently if its stdin
>is a terminal or not. 

Such programs are quite uncommon, and usually, it's a bad
idea to make such checks anyway. 

>Or when you simply would prefer the subprocess to die if it
attempts to >read from its stdin rather than block

For this case, I would say that it's more common to pass
/dev/null than a closed file descriptor. It's uncommon with
shell scripts that does "someprogram <&4711". It's much more
common with "someprogram </dev/null". With subprocess, this
is already easy:

...stdin=open("/dev/null"). 

>Using Popen instead of call is s simpler workaround than
>creating and closing a file descriptor and passing it in.

How would you use Popen in this case?

>Perhaps what is needed is a new constant, subprocess.CLOSED
>which creates a new file descriptor and closes it? This
>would be useful for Popen too, allowing call() to remain a
>think and trivially documented wrapper?

It's not very hard to get an unused FD:

closed_fd = os.open("/dev/null", os.O_RDONLY);
os.close(closed_fd)

I'm a bit reluctant to add a new constant when you can solve
the problem anyway with one line of code. 

Also, we'll need to think about the platform portability a
bit. Currently, I think that if we should add anything at
all, it should be a constant like subprocess.NULL, which
would be basically like open("/dev/null"), but also 
portable to Windows. 


----------------------------------------------------------------------

Comment By: Stuart Bishop (zenzen)
Date: 2005-06-22 08:12

Message:
Logged In: YES 
user_id=46639

I can't think of any uses cases for wanting to create an
inaccessible pipe and give it to the child. 

Wanting to pass a closed file handle is common. It is needed
when calling a program that behaves differently if its stdin
is a terminal or not. Or when you simply would prefer the
subprocess to die if it attempts to read from its stdin
rather than block.

Using Popen instead of call is s simpler workaround than
creating and closing a file descriptor and passing it in.

Perhaps what is needed is a new constant, subprocess.CLOSED
which creates a new file descriptor and closes it? This
would be useful for Popen too, allowing call() to remain a
think and trivially documented wrapper?

----------------------------------------------------------------------

Comment By: Peter Åstrand (astrand)
Date: 2005-06-21 18:08

Message:
Logged In: YES 
user_id=344921

>It makes no sense not to close stdin if it is PIPE
>because the stream cannot be accessed

True, but what if you actually *want* to create an
inaccessible pipe, and give it to the child?

Currently, the call() wrapper is *very* short and simple. I
think this is very good. For example, it allows us to
document it in two sentences. You get what you ask for: If
you use call() with strange arguments, you'll get a somewhat
strange behavíour. I see no point in introducing lots of
sanity checks in the wrapper functions. 

>The use case for this is ensuring a subprocess that
>detects if it is connected to a terminal or not runs in
>batch' mode, and that it will die instead of hang if
>it unexpectidly attempts to read from stdin

I'm not sure I understand what you want, but if you want to
have stdin connected to a closed file descriptor, just pass one:

>>> from subprocess import call, PIPE
>>> rv = call(['/usr/bin/bzip2', '-c'], stdout=PIPE,
stdin=4711)

(Of course, you should verify that 4711 is unused.)

If you don't agree with me, post to python-dev for discussion. 

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1220113&group_id=5470


More information about the Python-bugs-list mailing list