porting shell scripts: system(list), system_pipe(lists)

Donn Cave donn at drizzle.com
Thu Oct 2 07:43:56 CEST 2003


Quoth eichin at metacarta.com:
...
|  1. Am I being dense? Are there already common modules (included or
|     otherwise) that do this, or solve the problem some other way?

I can't tell you whether any of them has come to be common, but
there have been a handful of efforts along these lines - process
and pipeline creation.

|  2. Is there a more pythonic way of expressing the construction?
|     Would exposing the internal array of commands make more sense,
|     possibly by "passing through" various array operations on the
|     class to the internal array (as the use of "append" hints at)?  Or
|     maybe "exec" objects that a "pipe" combiner operates on?

Only thing that comes to mind is error handling.  It certainly is
not characteristic of Python functions to return an error status,
rather they typically raise exceptions.  Ideally, I would think
the exception type for this would carry the exit status, other
information in the status word, and text from error/diagnostic
output.  That last one is particularly important and particularly
awkward to get.

See appended example for a trick to deal with the special case
where a Python exception is caught in the fork.

|  3. Should an interface like this be in a "battery" somewhere? shutil
|     didn't seem to quite match...

No one ever likes anyone else's version of this, so it's typically
reinvented as required.

|  4. Any reason to even try porting this interface to non-unix systems?
|     Is there a close enough match to os.pipe/os.fork/os.exec/os.wait,
|     or some other construct that works on microsoft platforms?

There's os.spawnv, if you haven't noticed that.

	Donn Cave, donn at drizzle.com
-----------
import fcntl
import posix
import sys
import pickle

def spawn_wnw(wait, file, args, env):
	p0, p1 = posix.pipe()
	pid = posix.fork()
	if pid:
		posix.close(p1)
		ps = posix.read(p0, 1024)
		posix.close(p0)
		if wait:
			junk, ret = posix.waitpid(pid, 0)
		else:
			ret = pid
		if ps:
			e, v = pickle.loads(ps)
			raise e, v
		else:
			return ret
	else:
		try:
			fcntl.fcntl(p1, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
			posix.close(p0)
			posix.execve(file, args, env)
		except:
			e, v, t = sys.exc_info()
			s = pickle.dumps((e, v))
			posix.write(p1, s)
			posix._exit(117)

def spawnw(file, args, env):
	spawn_wnw(1, file, args, env)

def spawn(file, args, env):
	spawn_wnw(0, file, args, env)

pid = spawn('/bin/bummer', ['bummer', '-ever', 'summer'], posix.environ)




More information about the Python-list mailing list