spawn.py revision a4d132a868902ee2f1d73bf50de7af229ae72991
1"""distutils.spawn 2 3Provides the 'spawn()' function, a front-end to various platform- 4specific functions for launching another program in a sub-process.""" 5 6# created 1999/07/24, Greg Ward 7 8__rcsid__ = "$Id$" 9 10import sys, os, string 11from distutils.errors import * 12 13 14def spawn (cmd, 15 search_path=1, 16 verbose=0, 17 dry_run=0): 18 19 """Run another program, specified as a command list 'cmd', in a new 20 process. 'cmd' is just the argument list for the new process, ie. 21 cmd[0] is the program to run and cmd[1:] are the rest of its 22 arguments. There is no way to run a program with a name different 23 from that of its executable. 24 25 If 'search_path' is true (the default), the system's executable 26 search path will be used to find the program; otherwise, cmd[0] must 27 be the exact path to the executable. If 'verbose' is true, a 28 one-line summary of the command will be printed before it is run. 29 If 'dry_run' is true, the command will not actually be run. 30 31 Raise DistutilsExecError if running the program fails in any way; 32 just return on success.""" 33 34 if os.name == 'posix': 35 _spawn_posix (cmd, search_path, verbose, dry_run) 36 elif os.name == 'nt': 37 _spawn_nt (cmd, search_path, verbose, dry_run) 38 else: 39 raise DistutilsPlatformError, \ 40 "don't know how to spawn programs on platform '%s'" % os.name 41 42# spawn () 43 44 45def _spawn_nt ( cmd, 46 search_path=1, 47 verbose=0, 48 dry_run=0): 49 executable = cmd[0] 50 if search_path: 51 paths = string.split( os.environ['PATH'], os.pathsep) 52 base,ext = os.path.splitext(executable) 53 if (ext != '.exe'): 54 executable = executable + '.exe' 55 if not os.path.isfile(executable): 56 paths.reverse() # go over the paths and keep the last one 57 for p in paths: 58 f = os.path.join( p, executable ) 59 if os.path.isfile ( f ): 60 # the file exists, we have a shot at spawn working 61 executable = f 62 if verbose: 63 print string.join ( [executable] + cmd[1:], ' ') 64 if not dry_run: 65 # spawn for NT requires a full path to the .exe 66 rc = os.spawnv (os.P_WAIT, executable, cmd) 67 if rc != 0: 68 raise DistutilsExecError("command failed: %d" % rc) 69 70 71 72def _spawn_posix (cmd, 73 search_path=1, 74 verbose=0, 75 dry_run=0): 76 77 if verbose: 78 print string.join (cmd, ' ') 79 if dry_run: 80 return 81 exec_fn = search_path and os.execvp or os.execv 82 83 pid = os.fork () 84 85 if pid == 0: # in the child 86 try: 87 #print "cmd[0] =", cmd[0] 88 #print "cmd =", cmd 89 exec_fn (cmd[0], cmd) 90 except OSError, e: 91 sys.stderr.write ("unable to execute %s: %s\n" % 92 (cmd[0], e.strerror)) 93 os._exit (1) 94 95 sys.stderr.write ("unable to execute %s for unknown reasons" % cmd[0]) 96 os._exit (1) 97 98 99 else: # in the parent 100 # Loop until the child either exits or is terminated by a signal 101 # (ie. keep waiting if it's merely stopped) 102 while 1: 103 (pid, status) = os.waitpid (pid, 0) 104 if os.WIFSIGNALED (status): 105 raise DistutilsExecError, \ 106 "command %s terminated by signal %d" % \ 107 (cmd[0], os.WTERMSIG (status)) 108 109 elif os.WIFEXITED (status): 110 exit_status = os.WEXITSTATUS (status) 111 if exit_status == 0: 112 return # hey, it succeeded! 113 else: 114 raise DistutilsExecError, \ 115 "command %s failed with exit status %d" % \ 116 (cmd[0], exit_status) 117 118 elif os.WIFSTOPPED (status): 119 continue 120 121 else: 122 raise DistutilsExecError, \ 123 "unknown error executing %s: termination status %d" % \ 124 (cmd[0], status) 125# _spawn_posix () 126