Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Raising exception on STDIN read

Reply
Thread Tools

Raising exception on STDIN read

 
 
Ian Clark
Guest
Posts: n/a
 
      02-28-2008
On 2008-02-27, Gabriel Genellina <(E-Mail Removed)> wrote:
> En Wed, 27 Feb 2008 15:06:36 -0200, Ian Clark <(E-Mail Removed)>
> escribi�:
>
>> On 2008-02-27, Michael Goerz <(E-Mail Removed)4ward.com> wrote:
>>> Hi,
>>>
>>> I would like to raise an exception any time a subprocess tries to read
>>> from STDIN:
>>>
>>> latexprocess = subprocess.Popen( \
>>> 'pdflatex' + " " \
>>> + 'test' + " 2>&1", \
>>> shell=True, \
>>> cwd=os.getcwd(), \
>>> env=os.environ, \
>>> stdin=StdinCatcher() # any ideas here?
>>> )
>>>
>>> An exception should be raised whenever the pdflatex process
>>> reads from STDIN... and I have no idea how to do it. Any suggestions?

>
>> How about with a file-like object? I haven't tested this with subprocess
>> so you might want to read the manual on files if it doesn't work[1].

>
> Won't work for an external process, as pdflatex (and the OS) knows nothing
> about Python objects. The arguments to subprocess.Popen must be actual
> files having real OS file descriptors.


Taken from the subprocess documentation (emphasis mine). [1]

stdin, stdout and stderr specify the executed programs' standard
input, standard output and standard error file handles,
respectively. Valid values are PIPE, an existing file descriptor (a
positive integer), *an existing file object*, and None.

The following peice of code works fine for me with the subprocess
module. NOTE: the only difference from this and the last I posted is
that I set fileno() to _error().

import sys
import subprocess

class ErrorFile(object):
def _error(self, *args, **kwargs):
raise AssertionError("Illegal Access")

def _noop(self, *args, **kwargs):
pass

close = flush = seek = tell = _noop
next = read = readline = readlines = xreadlines = tuncate = _error
truncate = write = writelines = fileno = _error
# ^^^^^^

proc = subprocess.Popen("cat -", shell=True, stdin=ErrorFile())
ret = proc.wait()
print "return", ret

Ian

[1] http://docs.python.org/lib/node528.html

 
Reply With Quote
 
 
 
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-28-2008
En Thu, 28 Feb 2008 14:29:04 -0200, Ian Clark <(E-Mail Removed)>
escribió:

> On 2008-02-27, Gabriel Genellina <(E-Mail Removed)> wrote:
>> En Wed, 27 Feb 2008 15:06:36 -0200, Ian Clark <(E-Mail Removed)>
>> escribi�:
>>
>>> On 2008-02-27, Michael Goerz <(E-Mail Removed)4ward.com> wrote:
>>>> Hi,
>>>>
>>>> I would like to raise an exception any time a subprocess tries to read
>>>> from STDIN:
>>>>
>>>> latexprocess = subprocess.Popen( \
>>>> 'pdflatex' + " " \
>>>> + 'test' + " 2>&1", \
>>>> shell=True, \
>>>> cwd=os.getcwd(), \
>>>> env=os.environ, \
>>>> stdin=StdinCatcher() # any ideas here?
>>>> )
>>>>
>>>> An exception should be raised whenever the pdflatex process
>>>> reads from STDIN... and I have no idea how to do it. Any suggestions?

>>
>>> How about with a file-like object? I haven't tested this with
>>> subprocess
>>> so you might want to read the manual on files if it doesn't work[1].

>>
>> Won't work for an external process, as pdflatex (and the OS) knows
>> nothing
>> about Python objects. The arguments to subprocess.Popen must be actual
>> files having real OS file descriptors.

>
> Taken from the subprocess documentation (emphasis mine). [1]
>
> stdin, stdout and stderr specify the executed programs' standard
> input, standard output and standard error file handles,
> respectively. Valid values are PIPE, an existing file descriptor (a
> positive integer), *an existing file object*, and None.
>
> The following peice of code works fine for me with the subprocess
> module. NOTE: the only difference from this and the last I posted is
> that I set fileno() to _error().
>
> import sys
> import subprocess
>
> class ErrorFile(object):
> def _error(self, *args, **kwargs):
> raise AssertionError("Illegal Access")
>
> def _noop(self, *args, **kwargs):
> pass
>
> close = flush = seek = tell = _noop
> next = read = readline = readlines = xreadlines = tuncate =
> _error
> truncate = write = writelines = fileno = _error
> # ^^^^^^
>
> proc = subprocess.Popen("cat -", shell=True, stdin=ErrorFile())
> ret = proc.wait()
> print "return", ret


I don't see how this could ever work. The shell knows nothing about your
ErrorFile objects. If subprocess.Popen doesn't reject that ErrorFile
instance, it's a bug. An ErrorFile instance is not "an existing file
object".


--
Gabriel Genellina

 
Reply With Quote
 
 
 
 
Ian Clark
Guest
Posts: n/a
 
      02-28-2008
On 2008-02-28, Gabriel Genellina <(E-Mail Removed)> wrote:
> En Thu, 28 Feb 2008 14:29:04 -0200, Ian Clark <(E-Mail Removed)>
> escribió:
>
>> On 2008-02-27, Gabriel Genellina <(E-Mail Removed)> wrote:
>>> En Wed, 27 Feb 2008 15:06:36 -0200, Ian Clark <(E-Mail Removed)>
>>> escribi�:
>>>
>>>> On 2008-02-27, Michael Goerz <(E-Mail Removed)4ward.com> wrote:
>>>>> Hi,
>>>>>
>>>>> I would like to raise an exception any time a subprocess tries to read
>>>>> from STDIN:
>>>>>
>>>>> latexprocess = subprocess.Popen( \
>>>>> 'pdflatex' + " " \
>>>>> + 'test' + " 2>&1", \
>>>>> shell=True, \
>>>>> cwd=os.getcwd(), \
>>>>> env=os.environ, \
>>>>> stdin=StdinCatcher() # any ideas here?
>>>>> )
>>>>>
>>>>> An exception should be raised whenever the pdflatex process
>>>>> reads from STDIN... and I have no idea how to do it. Any suggestions?
>>>
>>>> How about with a file-like object? I haven't tested this with
>>>> subprocess
>>>> so you might want to read the manual on files if it doesn't work[1].
>>>
>>> Won't work for an external process, as pdflatex (and the OS) knows
>>> nothing
>>> about Python objects. The arguments to subprocess.Popen must be actual
>>> files having real OS file descriptors.

>>
>> Taken from the subprocess documentation (emphasis mine). [1]
>>
>> stdin, stdout and stderr specify the executed programs' standard
>> input, standard output and standard error file handles,
>> respectively. Valid values are PIPE, an existing file descriptor (a
>> positive integer), *an existing file object*, and None.
>>
>> The following peice of code works fine for me with the subprocess
>> module. NOTE: the only difference from this and the last I posted is
>> that I set fileno() to _error().
>>
>> import sys
>> import subprocess
>>
>> class ErrorFile(object):
>> def _error(self, *args, **kwargs):
>> raise AssertionError("Illegal Access")
>>
>> def _noop(self, *args, **kwargs):
>> pass
>>
>> close = flush = seek = tell = _noop
>> next = read = readline = readlines = xreadlines = tuncate =
>> _error
>> truncate = write = writelines = fileno = _error
>> # ^^^^^^
>>
>> proc = subprocess.Popen("cat -", shell=True, stdin=ErrorFile())
>> ret = proc.wait()
>> print "return", ret

>
> I don't see how this could ever work. The shell knows nothing about your
> ErrorFile objects. If subprocess.Popen doesn't reject that ErrorFile
> instance, it's a bug. An ErrorFile instance is not "an existing file
> object".


Could you please explain why this won't work. ErrorFile exposes most all
attributes of file objects, so I don't understand why it wouldn't be
considered a file object.

Did you try running the code by any chance? It works fine for me on
2.5.1 on Linux.

Ian

 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      02-28-2008
En Thu, 28 Feb 2008 15:22:21 -0200, Ian Clark <(E-Mail Removed)>
escribió:

> On 2008-02-28, Gabriel Genellina <(E-Mail Removed)> wrote:
>> En Thu, 28 Feb 2008 14:29:04 -0200, Ian Clark <(E-Mail Removed)>
>> escribió:
>>
>>> On 2008-02-27, Gabriel Genellina <(E-Mail Removed)> wrote:
>>>> En Wed, 27 Feb 2008 15:06:36 -0200, Ian Clark <(E-Mail Removed)>
>>>> escribi�:
>>>>
>>>>> On 2008-02-27, Michael Goerz <(E-Mail Removed)4ward.com>
>>>>> wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I would like to raise an exception any time a subprocess tries to
>>>>>> read
>>>>>> from STDIN:
>>>>>>
>>>>>> latexprocess = subprocess.Popen( \
>>>>>> 'pdflatex' + " " \
>>>>>> + 'test' + " 2>&1", \
>>>>>> shell=True, \
>>>>>> cwd=os.getcwd(), \
>>>>>> env=os.environ, \
>>>>>> stdin=StdinCatcher() # any ideas here?
>>>>>> )
>>>>>>
>>>>>> An exception should be raised whenever the pdflatex process
>>>>>> reads from STDIN... and I have no idea how to do it. Any
>>>>>> suggestions?
>>>>
>>>>> How about with a file-like object? I haven't tested this with
>>>>> subprocess
>>>>> so you might want to read the manual on files if it doesn't work[1].
>>>>
>>>> Won't work for an external process, as pdflatex (and the OS) knows
>>>> nothing
>>>> about Python objects. The arguments to subprocess.Popen must be actual
>>>> files having real OS file descriptors.
>>>
>>> Taken from the subprocess documentation (emphasis mine). [1]
>>>
>>> stdin, stdout and stderr specify the executed programs' standard
>>> input, standard output and standard error file handles,
>>> respectively. Valid values are PIPE, an existing file descriptor (a
>>> positive integer), *an existing file object*, and None.
>>>
>>> The following peice of code works fine for me with the subprocess
>>> module. NOTE: the only difference from this and the last I posted is
>>> that I set fileno() to _error().
>>>
>>> import sys
>>> import subprocess
>>>
>>> class ErrorFile(object):
>>> def _error(self, *args, **kwargs):
>>> raise AssertionError("Illegal Access")
>>>
>>> def _noop(self, *args, **kwargs):
>>> pass
>>>
>>> close = flush = seek = tell = _noop
>>> next = read = readline = readlines = xreadlines = tuncate =
>>> _error
>>> truncate = write = writelines = fileno = _error
>>> # ^^^^^^
>>>
>>> proc = subprocess.Popen("cat -", shell=True, stdin=ErrorFile())
>>> ret = proc.wait()
>>> print "return", ret

>>
>> I don't see how this could ever work. The shell knows nothing about your
>> ErrorFile objects. If subprocess.Popen doesn't reject that ErrorFile
>> instance, it's a bug. An ErrorFile instance is not "an existing file
>> object".

>
> Could you please explain why this won't work. ErrorFile exposes most all
> attributes of file objects, so I don't understand why it wouldn't be
> considered a file object.
>
> Did you try running the code by any chance? It works fine for me on
> 2.5.1 on Linux.


Define "works fine". I bet you get an exception - but *before* the child
process starts (and no, I didn't try the code, but certainly I would be
greatly surprised if it actually worked)

Consider the following: The child process may be anything, totally unaware
of Python objects. As any other process, it reads from standard input,
writes to standard output and maybe to standard error too. Those are
predefined file descriptors (0, 1, 2) provided by the operating system
itself. When the child process calls write(1, "hello\n") it isn't calling
the write method of a Python object, it's calling a C runtime function (or
system function). Note that `write` requires a *file descriptor*, an OS
concept, not a Python object. This is why the documentation for subprocess
states that those parameters must be: an integer --that is, a file
descriptor-- which is used as it is; an *actual* file object having a
fileno() method (it is used to get the file descriptor); the PIPE marker
(an OS pipe is created and its two descriptors are used on parent and
child); or None.

I hope it's more clear now. Python objects are only meaningful *inside* a
Python program, but an *external* program can't use them directly.
A simple example:

import subprocess
import sys

print "One"
sys.stdout = open("out.txt","w")
print "Two"
subprocess.call("ls", shell=True)
print "Three"

Try to guess where each output line, and the ls outout, will appear.

--
Gabriel Genellina

 
Reply With Quote
 
Ian Clark
Guest
Posts: n/a
 
      02-29-2008
On 2008-02-28, Gabriel Genellina <(E-Mail Removed)> wrote:
> I hope it's more clear now. Python objects are only meaningful *inside* a
> Python program, but an *external* program can't use them directly.


Yes, sorry. This is what I was getting hung up on. My thinking was that
subprocess was orchestrating it such that any reads would be funneled
back into the Python object. Granted, that was my gut reaction to it.
Thinking (and playing) with it a bit more I now realize that that makes
no sense. Thank you for reminding me about the seperation of OS and
Python files.

Ian

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
peek at stdin, flush stdin Johnathan Doe C Programming 5 05-17-2013 04:30 PM
How to pass stdin of a C++ program to the stdin of a process createdwith ShellExecute() Ben C Programming 2 08-29-2009 09:47 PM
STDIN, OUT, ERR and $stdin, out, err - Differences? Terry Cooper Ruby 7 06-09-2009 05:48 AM
Reading from stdin then launching a program that reads from stdin strange behaviour Stefano Sabatini Perl Misc 6 07-29-2007 10:38 PM
Reading stdin once confuses second stdin read Charlie Zender C Programming 6 06-21-2004 01:39 PM



Advertisments