user1192062
user1192062

Reputation: 51

Blocking writing to stdout

I'm writing a Python script that will use subprocesses. The main idea is to have one parent script that runs specialised child scripts, which e.g. run other programs or do some stuff on their own. There are pipes between parent script and subprocesses. I use them to control whether subprocess is still responding by sending some characters on regular basis and checking the response. The problem is that when the subprocess prints anything on screen (i.e. writes to stdout or stderr), the pipes are broken and everything crashes. So my main question is whether it is possible to block writing to std* in the subprocess, so only legitimate response written to pipe would be possible? I have already tried Stop a function from writing to stdout but without any success.

Also other ideas for communcation between parent and subprocess are welcome (except file based pipes). However, the subprocesses must be used.

Upvotes: 2

Views: 2414

Answers (2)

Dr. Jan-Philip Gehrcke
Dr. Jan-Philip Gehrcke

Reputation: 35796

I strongly believe that you do not just have to accept "that when the subprocess prints anything on screen (i.e. writes to stdout or stderr), the pipes are broken and everything crashes". You can solve this problem. Then you do not need to "block" the subprocesses from writing to standard streams.

Make proper use of all the power of the subprocess module. First of all, connect a subprocess.PIPE to each of the standard streams of a subprocess:

p = subprocess.Popen(
        [executable, arg1, arg2],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)

Run the subprocess and interact with it through those pipes:

stdout, stderr = p.communicate(stdin="command")

If communicate() is not flexible enough (if you need to monitor several subprocesses at the same time and/or if the stdin data to a certain subprocess depends on its output in response to a previous command) you can directly interact with the p.stdout, p.stderr, p.stdin attributes. In this case, you will likely have to build your own monitoring loop and make use of p.poll() and/or p.returncode. Controlling the subprocesses can also be realized via p.send_signal().

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363787

You can pass a function to subprocess.Popen that is executed prior to executing the requested program:

def close_std():
    os.close(0)
    os.close(1)
    os.close(2)

p = subprocess.Popen(cmd, preexec_fn=close_std)

Note the use of low-level os.close; closing sys.std* will only have effect in the forked Python process. Also, be aware that if your underlying programs are Python scripts, they may die due to an exception when they try to write to closed file descriptors.

Upvotes: 0

Related Questions