should these be fixed for python 2.4?

Alexander Schmolck a.schmolck at gmx.net
Sat Oct 2 13:57:31 CEST 2004


"Martin v. Löwis" <martin at v.loewis.de> writes:

> Alexander Schmolck wrote:
>> OK, but let me say that this is *not* obvious -- it is difficult to find in
>> the docs (I don't really want to spawn anything and it's burried amongst a
>> zillion cryptically named similar functions with a complex interface) and
>> difficult to use.
>
> I fail to see the last point. What you proposed is equally difficult to
> use.

  ``os.run('touch', 'foo')`` [1]

vs.

  ``os.spawnvp(os.P_WAIT, 'touch', ['touch', 'foo'])``

If you don't think that second is not about 1 order of magnitude more
difficult to use for Joe Programmer, you are likely to be mistaken.

Even assuming that Joe, who presumably doesn't have a clue what spawning a
process might be and just wants to "run touch" (or whatever) has somehow
miraculously discovered that it's not `os.system` but spawning a process what
he really needs he's still faced with several hurdles (Which spawn* is the
right one? What does all that funny jargon in the docs mean? What were the
right arguments again? Ooops, I forgot to pass the command I wanted to run as
an argument... Finally -- what are the chances of getting all these right from
memory?)

> And yes, you do want to spawn a new process.

I expressed myself poorly: what I meant is that me and other people who
mistakenly reach for `os.system' don't go to the docs thinking "I want to
spawn a new process, how do I best accomplish that?", but rather "I'd like to
run an external command for my utility script, how do I best accomplish that?".

This is conceptually simple and I'd imagine frequent desire; so I think it
should be accommodated by a simple function.

> Adding notes to documentation is always possible. I don't see the point
> of adding a convenience function, because os.spawn* is already there.

But it's not *convenient* (or simple to understand and remember; for example
you almost *never* want to pass a different name as first arg so it's very
easy to forget; it's also entirely non-obvious unless you happen to know that
under unix some ostensibly different commands are just symlinks to a single
exectuable that behaves differently based on what it finds in argv[0]).

Plus you equally want something with (cmd, *args) as opposed to (cmdstring)
semantics for popen-like stuff, I should think (and unless I'm again missing
something there is no function that already does it).

So for symmetry, I'd ideally like to see two additions, say `run` (returning
exit status) and `run_and_read` (or `read_process`) (returning exit status and
process (standard) output).

If that's asking too much I'd at least suggest: 

1) putting something in the os.system heading that gives a simple example when
   *not* to use os.system and why and what to do instead (see [1]).
2) Providing something like ``commands.mkarg`` that works reasonably reliably
   and is documented


'as


Footnotes: 
[1]  Here's a mock implementation (untested):

    def run(cmd, *args):
        """Run `cmd` (which is searched for in the executable path) with `args` and
        return the exit status. 

        In general (unless you know what you're doing) use::

         run('program', filename)

        rather than::

         os.system('program %s' % filename)

        because the latter will not work as expected if `filename` contains
        spaces or shell-metacharacters.

        If you need more fine-grained control look at ``os.spawn*``.
        """
        return spawnvp(P_WAIT, cmd, (cmd,) + args)



More information about the Python-list mailing list