Launching Sub-Processes

Because the select module is not available, you can't use the subprocess module in IronPython. Luckily there is an easy to use (but not as elegant) alternative - System.Diagnostics.Process. (This entry written with help from a post by Steve Gilham.)

Launch a subprocess, using the static method Start: from System.Diagnostics import Process

Process.Start('something.exe', 'args')

If you want stdout from the subprocess on your stdout, you have to jump through a few more hoops. The following example does this, plus waits for the subprocess to exit: p = Process p.StartInfo.UseShellExecute = False p.StartInfo.RedirectStandardOutput = True p.StartInfo.FileName = 'python' p.StartInfo.Arguments = 'somefile.py' p.Start p.WaitForExit If you want you can set environment variables for the subprocess: proc = Process proc.StartInfo.FileName = gnuplotPath proc.StartInfo.Arguments = '"%s"' % scriptPath proc.StartInfo.EnvironmentVariables['GDFONTPATH'] = fontPath proc.StartInfo.EnvironmentVariables['GNUPLOT_FONTPATH'] = fontPath proc.StartInfo.UseShellExecute = False proc.Start proc.WaitForExit Note: Please, be cautious about using process.OutputDataReceived event handlers. These don't handle binary subprocess output well, as the output is converted to Unicode before triggering the event. You might need to read directly from process.StandardOutput.BaseStream in a hand-made thread to bypass the automatic output conversion to Unicode.

The example above is for launching Gnuplot which needs two environment variables setting. When setting environment variables you have to UseShellExecute = False.

If you want to know the exit code of the process, check the ExitCode property once the process has completed.

partial 'subprocess' implementation
By Jeff Hardy, available here.

By Daniel Dotsenko, (Jeff's code circa 2009, changed to support binary output capture, redirecting to file-like or file descriptors, implemented communicate) available here.

subprocess/.NET comparison
This comparison may help people not familiar with .NET API.

subprocess: def run_command(args, input=None): """run_command(args, input=None) -> stdoutstring, stderrstring, returncode   Runs the command, giving the input if any.    The command is specified as a list: 'ls -l' would be sent as ['ls', '-l'].    Returns the standard output and error as strings, and the return code""" from subprocess import Popen, PIPE p = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr = p.communicate(input) return stdout, stderr, p.returncode

.NET: def run_command(args, input=None): from System.Diagnostics import Process p = Process have_stdin = input is not None p.StartInfo.UseShellExecute = False p.StartInfo.RedirectStandardInput = have_stdin p.StartInfo.RedirectStandardOutput = True p.StartInfo.RedirectStandardError = True p.StartInfo.FileName = args[0]

# not a precise way to join these! See list2cmdline in CPython's subprocess.py for the proper way. p.StartInfo.Arguments = " ".join(args[1:])

p.Start if have_stdinA: p.StandardInput.Write(input) p.WaitForExit stdout = p.StandardOutput.ReadToEnd stderr = p.StandardError.ReadToEnd return stdout, stderr, p.ExitCode

Back to Contents.