distutils 中的 _spawn_posix 是否总是引发错误?
Does _spawn_posix in distutils always raise an error?
我不敢将它发送到 distutils
邮件列表,因为我很确定我在做一个愚蠢的误解。
这是 distutils
2.7.9 版中的函数 _spawn_posix
:
def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
log.info(' '.join(cmd))
if dry_run:
return
executable = cmd[0]
exec_fn = search_path and os.execvp or os.execv
env = None
if sys.platform == 'darwin':
global _cfg_target, _cfg_target_split
if _cfg_target is None:
_cfg_target = sysconfig.get_config_var(
'MACOSX_DEPLOYMENT_TARGET') or ''
if _cfg_target:
_cfg_target_split = [int(x) for x in _cfg_target.split('.')]
if _cfg_target:
# ensure that the deployment target of build process is not less
# than that used when the interpreter was built. This ensures
# extension modules are built with correct compatibility values
cur_target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', _cfg_target)
if _cfg_target_split > [int(x) for x in cur_target.split('.')]:
my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: '
'now "%s" but "%s" during configure'
% (cur_target, _cfg_target))
raise DistutilsPlatformError(my_msg)
env = dict(os.environ,
MACOSX_DEPLOYMENT_TARGET=cur_target)
exec_fn = search_path and os.execvpe or os.execve
pid = os.fork()
if pid == 0: # in the child
try:
if env is None:
exec_fn(executable, cmd)
else:
exec_fn(executable, cmd, env)
except OSError, e:
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r: %s\n" %
(cmd, e.strerror))
os._exit(1)
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r for unknown reasons" % cmd)
os._exit(1)
else: # in the parent
# Loop until the child either exits or is terminated by a signal
# (ie. keep waiting if it's merely stopped)
while 1:
try:
pid, status = os.waitpid(pid, 0)
except OSError, exc:
import errno
if exc.errno == errno.EINTR:
continue
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r failed: %s" % (cmd, exc[-1])
if os.WIFSIGNALED(status):
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r terminated by signal %d" % \
(cmd, os.WTERMSIG(status))
elif os.WIFEXITED(status):
exit_status = os.WEXITSTATUS(status)
if exit_status == 0:
return # hey, it succeeded!
else:
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r failed with exit status %d" % \
(cmd, exit_status)
elif os.WIFSTOPPED(status):
continue
else:
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"unknown error executing %r: termination status %d" % \
(cmd, status)
显然那里有很多。没有人想读那个。您需要做的就是:
- 找到行
exec_fn(executable, cmd)
。这就是整个函数设置为执行的行。它调用 os.execvp
.
- 注意
exec_fn
仅在 pid == 0
时调用。
注意当pid == 0
时,会调用下面的代码:
try:
if env is None:
exec_fn(executable, cmd)
else:
exec_fn(executable, cmd, env)
except OSError, e:
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r: %s\n" %
(cmd, e.strerror))
os._exit(1)
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r for unknown reasons" % cmd)
os._exit(1)
注意这里,如果在 try
块中引发 OSError
,我们将以状态 1(失败)退出系统。
- 请注意,即使
OSError
未 引发,我们 仍 以状态 1 退出系统(失败)。
- 在这两种情况下,一直在等待子进程完成的父进程引发
DistutilsExecError
。
有人可以指出我的错误吗?还是我碰巧使用的 distutils
版本有一个疯狂的错误,此错误已被修复?
啊哈,好的,docs 说一下 os.execvp
和其他 os.exec
函数
These functions all execute a new program, replacing the current process; they do not return. On Unix, the new executable is loaded into the current process, and will have the same process id as the caller. Errors will be reported as OSError exceptions.
因此,一旦调用 exec_fn
,如果成功,则永远不会执行后面的行。它们已被新的 os.execvp
流程所取代。
我不敢将它发送到 distutils
邮件列表,因为我很确定我在做一个愚蠢的误解。
这是 distutils
2.7.9 版中的函数 _spawn_posix
:
def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0):
log.info(' '.join(cmd))
if dry_run:
return
executable = cmd[0]
exec_fn = search_path and os.execvp or os.execv
env = None
if sys.platform == 'darwin':
global _cfg_target, _cfg_target_split
if _cfg_target is None:
_cfg_target = sysconfig.get_config_var(
'MACOSX_DEPLOYMENT_TARGET') or ''
if _cfg_target:
_cfg_target_split = [int(x) for x in _cfg_target.split('.')]
if _cfg_target:
# ensure that the deployment target of build process is not less
# than that used when the interpreter was built. This ensures
# extension modules are built with correct compatibility values
cur_target = os.environ.get('MACOSX_DEPLOYMENT_TARGET', _cfg_target)
if _cfg_target_split > [int(x) for x in cur_target.split('.')]:
my_msg = ('$MACOSX_DEPLOYMENT_TARGET mismatch: '
'now "%s" but "%s" during configure'
% (cur_target, _cfg_target))
raise DistutilsPlatformError(my_msg)
env = dict(os.environ,
MACOSX_DEPLOYMENT_TARGET=cur_target)
exec_fn = search_path and os.execvpe or os.execve
pid = os.fork()
if pid == 0: # in the child
try:
if env is None:
exec_fn(executable, cmd)
else:
exec_fn(executable, cmd, env)
except OSError, e:
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r: %s\n" %
(cmd, e.strerror))
os._exit(1)
if not DEBUG:
cmd = executable
sys.stderr.write("unable to execute %r for unknown reasons" % cmd)
os._exit(1)
else: # in the parent
# Loop until the child either exits or is terminated by a signal
# (ie. keep waiting if it's merely stopped)
while 1:
try:
pid, status = os.waitpid(pid, 0)
except OSError, exc:
import errno
if exc.errno == errno.EINTR:
continue
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r failed: %s" % (cmd, exc[-1])
if os.WIFSIGNALED(status):
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r terminated by signal %d" % \
(cmd, os.WTERMSIG(status))
elif os.WIFEXITED(status):
exit_status = os.WEXITSTATUS(status)
if exit_status == 0:
return # hey, it succeeded!
else:
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"command %r failed with exit status %d" % \
(cmd, exit_status)
elif os.WIFSTOPPED(status):
continue
else:
if not DEBUG:
cmd = executable
raise DistutilsExecError, \
"unknown error executing %r: termination status %d" % \
(cmd, status)
显然那里有很多。没有人想读那个。您需要做的就是:
- 找到行
exec_fn(executable, cmd)
。这就是整个函数设置为执行的行。它调用os.execvp
. - 注意
exec_fn
仅在pid == 0
时调用。 注意当
pid == 0
时,会调用下面的代码:try: if env is None: exec_fn(executable, cmd) else: exec_fn(executable, cmd, env) except OSError, e: if not DEBUG: cmd = executable sys.stderr.write("unable to execute %r: %s\n" % (cmd, e.strerror)) os._exit(1) if not DEBUG: cmd = executable sys.stderr.write("unable to execute %r for unknown reasons" % cmd) os._exit(1)
注意这里,如果在
try
块中引发OSError
,我们将以状态 1(失败)退出系统。- 请注意,即使
OSError
未 引发,我们 仍 以状态 1 退出系统(失败)。 - 在这两种情况下,一直在等待子进程完成的父进程引发
DistutilsExecError
。
有人可以指出我的错误吗?还是我碰巧使用的 distutils
版本有一个疯狂的错误,此错误已被修复?
啊哈,好的,docs 说一下 os.execvp
和其他 os.exec
函数
These functions all execute a new program, replacing the current process; they do not return. On Unix, the new executable is loaded into the current process, and will have the same process id as the caller. Errors will be reported as OSError exceptions.
因此,一旦调用 exec_fn
,如果成功,则永远不会执行后面的行。它们已被新的 os.execvp
流程所取代。