0001 """distutils.spawn 0002 0003 Provides the 'spawn()' function, a front-end to various platform- 0004 specific functions for launching another program in a sub-process. 0005 Also provides the 'find_executable()' to search the path for a given 0006 executable name. 0007 """ 0008 0009 # This module should be kept compatible with Python 1.5.2. 0010 0011 __revision__ = "$Id: spawn.py,v 1.18 2004/07/18 06:14:42 tim_one Exp $" 0012 0013 import sys, os, string 0014 from distutils.errors import * 0015 from distutils import log 0016 0017 def spawn (cmd, 0018 search_path=1, 0019 verbose=0, 0020 dry_run=0): 0021 0022 """Run another program, specified as a command list 'cmd', in a new 0023 process. 'cmd' is just the argument list for the new process, ie. 0024 cmd[0] is the program to run and cmd[1:] are the rest of its arguments. 0025 There is no way to run a program with a name different from that of its 0026 executable. 0027 0028 If 'search_path' is true (the default), the system's executable 0029 search path will be used to find the program; otherwise, cmd[0] 0030 must be the exact path to the executable. If 'dry_run' is true, 0031 the command will not actually be run. 0032 0033 Raise DistutilsExecError if running the program fails in any way; just 0034 return on success. 0035 """ 0036 if os.name == 'posix': 0037 _spawn_posix(cmd, search_path, dry_run=dry_run) 0038 elif os.name == 'nt': 0039 _spawn_nt(cmd, search_path, dry_run=dry_run) 0040 elif os.name == 'os2': 0041 _spawn_os2(cmd, search_path, dry_run=dry_run) 0042 else: 0043 raise DistutilsPlatformError, \ 0044 "don't know how to spawn programs on platform '%s'" % os.name 0045 0046 # spawn () 0047 0048 0049 def _nt_quote_args (args): 0050 """Quote command-line arguments for DOS/Windows conventions: just 0051 wraps every argument which contains blanks in double quotes, and 0052 returns a new argument list. 0053 """ 0054 0055 # XXX this doesn't seem very robust to me -- but if the Windows guys 0056 # say it'll work, I guess I'll have to accept it. (What if an arg 0057 # contains quotes? What other magic characters, other than spaces, 0058 # have to be escaped? Is there an escaping mechanism other than 0059 # quoting?) 0060 0061 for i in range(len(args)): 0062 if string.find(args[i], ' ') != -1: 0063 args[i] = '"%s"' % args[i] 0064 return args 0065 0066 def _spawn_nt (cmd, 0067 search_path=1, 0068 verbose=0, 0069 dry_run=0): 0070 0071 executable = cmd[0] 0072 cmd = _nt_quote_args(cmd) 0073 if search_path: 0074 # either we find one or it stays the same 0075 executable = find_executable(executable) or executable 0076 log.info(string.join([executable] + cmd[1:], ' ')) 0077 if not dry_run: 0078 # spawn for NT requires a full path to the .exe 0079 try: 0080 rc = os.spawnv(os.P_WAIT, executable, cmd) 0081 except OSError, exc: 0082 # this seems to happen when the command isn't found 0083 raise DistutilsExecError, \ 0084 "command '%s' failed: %s" % (cmd[0], exc[-1]) 0085 if rc != 0: 0086 # and this reflects the command running but failing 0087 raise DistutilsExecError, \ 0088 "command '%s' failed with exit status %d" % (cmd[0], rc) 0089 0090 0091 def _spawn_os2 (cmd, 0092 search_path=1, 0093 verbose=0, 0094 dry_run=0): 0095 0096 executable = cmd[0] 0097 #cmd = _nt_quote_args(cmd) 0098 if search_path: 0099 # either we find one or it stays the same 0100 executable = find_executable(executable) or executable 0101 log.info(string.join([executable] + cmd[1:], ' ')) 0102 if not dry_run: 0103 # spawnv for OS/2 EMX requires a full path to the .exe 0104 try: 0105 rc = os.spawnv(os.P_WAIT, executable, cmd) 0106 except OSError, exc: 0107 # this seems to happen when the command isn't found 0108 raise DistutilsExecError, \ 0109 "command '%s' failed: %s" % (cmd[0], exc[-1]) 0110 if rc != 0: 0111 # and this reflects the command running but failing 0112 print "command '%s' failed with exit status %d" % (cmd[0], rc) 0113 raise DistutilsExecError, \ 0114 "command '%s' failed with exit status %d" % (cmd[0], rc) 0115 0116 0117 def _spawn_posix (cmd, 0118 search_path=1, 0119 verbose=0, 0120 dry_run=0): 0121 0122 log.info(string.join(cmd, ' ')) 0123 if dry_run: 0124 return 0125 exec_fn = search_path and os.execvp or os.execv 0126 0127 pid = os.fork() 0128 0129 if pid == 0: # in the child 0130 try: 0131 #print "cmd[0] =", cmd[0] 0132 #print "cmd =", cmd 0133 exec_fn(cmd[0], cmd) 0134 except OSError, e: 0135 sys.stderr.write("unable to execute %s: %s\n" % 0136 (cmd[0], e.strerror)) 0137 os._exit(1) 0138 0139 sys.stderr.write("unable to execute %s for unknown reasons" % cmd[0]) 0140 os._exit(1) 0141 0142 0143 else: # in the parent 0144 # Loop until the child either exits or is terminated by a signal 0145 # (ie. keep waiting if it's merely stopped) 0146 while 1: 0147 try: 0148 (pid, status) = os.waitpid(pid, 0) 0149 except OSError, exc: 0150 import errno 0151 if exc.errno == errno.EINTR: 0152 continue 0153 raise DistutilsExecError, \ 0154 "command '%s' failed: %s" % (cmd[0], exc[-1]) 0155 if os.WIFSIGNALED(status): 0156 raise DistutilsExecError, \ 0157 "command '%s' terminated by signal %d" % \ 0158 (cmd[0], os.WTERMSIG(status)) 0159 0160 elif os.WIFEXITED(status): 0161 exit_status = os.WEXITSTATUS(status) 0162 if exit_status == 0: 0163 return # hey, it succeeded! 0164 else: 0165 raise DistutilsExecError, \ 0166 "command '%s' failed with exit status %d" % \ 0167 (cmd[0], exit_status) 0168 0169 elif os.WIFSTOPPED(status): 0170 continue 0171 0172 else: 0173 raise DistutilsExecError, \ 0174 "unknown error executing '%s': termination status %d" % \ 0175 (cmd[0], status) 0176 # _spawn_posix () 0177 0178 0179 def find_executable(executable, path=None): 0180 """Try to find 'executable' in the directories listed in 'path' (a 0181 string listing directories separated by 'os.pathsep'; defaults to 0182 os.environ['PATH']). Returns the complete filename or None if not 0183 found. 0184 """ 0185 if path is None: 0186 path = os.environ['PATH'] 0187 paths = string.split(path, os.pathsep) 0188 (base, ext) = os.path.splitext(executable) 0189 if (sys.platform == 'win32' or os.name == 'os2') and (ext != '.exe'): 0190 executable = executable + '.exe' 0191 if not os.path.isfile(executable): 0192 for p in paths: 0193 f = os.path.join(p, executable) 0194 if os.path.isfile(f): 0195 # the file exists, we have a shot at spawn working 0196 return f 0197 return None 0198 else: 0199 return executable 0200 0201 # find_executable() 0202
Generated by PyXR 0.9.4