[Python-Dev] Why spawnvp not implemented on Windows?

Alexey Borzenkov snaury at gmail.com
Fri Oct 13 02:46:23 CEST 2006

Forgot to include python-dev...

On 10/13/06, "Martin v. Löwis" <martin at v.loewis.de> wrote:
> > Umm... do you mean that spawn*p* on python 2.5 is an absolute no?
> Yes. No new features can be added to Python 2.5.x; Python 2.5 has
> already been released.

Ugh... that's just not fair. Because of this there will be no spawn*p*
in python for another two years. x_x

I have a workaround for this, that tweaks os module:

[...snip wrong code...]

It should have been:

if (not (hasattr(os, 'spawnvpe') or hasattr(os, 'spawnvp'))
    and hasattr(os, 'spawnve') and hasattr(os, 'spawnv')):
    def _os__spawnvpe(mode, file, args, env=None):
        import sys
        from errno import ENOENT, ENOTDIR
        from os import path, spawnve, spawnv, environ, defpath, pathsep, error

        if env is not None:
            func = spawnve
            argrest = (args, env)
            func = spawnv
            argrest = (args,)
            env = environ

        head, tail = path.split(file)
        if head:
            return func(mode, file, *argrest)
        if 'PATH' in env:
            envpath = env['PATH']
            envpath = defpath
        PATH = envpath.split(pathsep)
        if os.name == 'nt' or os.name == 'os2':
            PATH.insert(0, '')
        saved_exc = None
        saved_tb = None
        for dir in PATH:
            fullname = path.join(dir, file)
                return func(mode, fullname, *argrest)
            except error, e:
                tb = sys.exc_info()[2]
                if (e.errno != ENOENT and e.errno != ENOTDIR
                    and saved_exc is None):
                    saved_exc = e
                    saved_tb = tb
        if saved_exc:
            raise error, saved_exc, saved_tb
        raise error, e, tb

    def _os_spawnvp(mode, file, args):
        return os._spawnvpe(mode, file, args)

    def _os_spawnvpe(mode, file, args, env):
        return os._spawnvpe(mode, file, args, env)

    def _os_spawnlp(mode, file, *args):
        return os._spawnvpe(mode, file, args)

    def _os_spawnlpe(mode, file, *args):
        return os._spawnvpe(mode, file, args[:-1], args[-1])

    os._spawnvpe = _os__spawnvpe
    os.spawnvp = _os_spawnvp
    os.spawnvpe = _os_spawnvpe
    os.spawnlp = _os_spawnlp
    os.spawnlpe = _os_spawnlpe
    os.__all__.extend(["spawnvp", "spawnvpe", "spawnlp", "spawnlpe"])

But the fact that I have to use similar code anywhere I need to use
spawnlp is not fair. Notice that _spawnvpe is simply a clone of
_execvpe from os.py, maybe if the problem is new API in c source, this
approach could be used in os.py?

P.S. Although it's a bit stretching, one might also say that
implementing spawn*p* on windows is not actually a new feature, and
rather is a bugfix for misfeature. Why every other platform can
benefit from spawn*p* and only Windows can't? This just makes
os.spawn*p* useless: it becomes unreliable and can't be used in
portable code at all.

More information about the Python-Dev mailing list