[GRASS-dev] question about python scripts on Windows again

Glynn Clements glynn at gclements.plus.com
Wed Jan 27 10:24:15 EST 2010


Michael Barton wrote:

> >> Some time back, I asked how users could create a python script that runs
> >> under GRASS for windows. At the time, the answer was more or less: 'with
> >> great difficulty, if even possible'. There have been quite a few changes
> >> in the Windows builds over the past month or so and I am wondering if
> >> the answer is more optimistic now.
> > 
> > The problem is that g.parser re-executes the script via $GRASS_SH,
> > which won't work for anything other than shell scripts. That hasn't
> > changed.
> > 
> 
> Thanks for the update.

There hasn't been an update; that's the problem ;)

> This is unfortunate and oddly ironic, since one of the rationales
> for the move to Python is that shell scripts must be run on Windows
> under a *nix emulator like msys, while Python can run native.
> 
> Given what you say, why do Python scripts run on other platforms?

Because the use of $GRASS_SH is specific to Windows:

#ifdef __MINGW32__
    {
	/* execlp() and _spawnlp ( _P_OVERLAY,..) do not work, they return 
	 * immediately and that breaks scripts running GRASS scripts
	 * because they dont wait until GRASS script finished */
	/* execlp( "sh", "sh", filename, "@ARGS_PARSED@", NULL); */
	/* _spawnlp ( _P_OVERLAY, "sh", "sh", filename, "@ARGS_PARSED@", NULL ); */
	int ret;
	char *shell = getenv("GRASS_SH");

	if (shell == NULL)
	    shell = "sh";
	ret =
	    _spawnlp(_P_WAIT, shell, shell, filename, "@ARGS_PARSED@", NULL);
	G_debug(1, "ret = %d", ret);
	if (ret == -1) {
	    perror("_spawnlp() failed");
	    return 1;
	}
	return ret;
    }
#else
    execl(filename, filename, "@ARGS_PARSED@", NULL);

    perror("execl() failed");
    return 1;
#endif

On Unix, we can just execl() the script, but that doesn't work on
Windows. The "quick fix" was to run the script via $GRASS_SH, which
was fine back when scripts were *always* shell scripts.

Alternatives include:

1. Parsing the #! line at the start of the script and selecting the
appropriate interpreter.

2. Adding a ".sh" extension to shell scripts, associating the ".sh"
extension with bash, and invoking the script via "cmd /c <command>".

3. Invoking the script via "$GRASS_SH -c '<command>'" and letting the
shell handle the #! line.

The main problem with both 2 and 3 is that we would need to construct
a suitable command line, quoting or escaping any characters which are
interpreted by the shell.

> > One solution is to merge the support for the -s switch from 7.0.
> 
> What does the -s switch do?

It writes the option settings to stdout then quits, rather than trying
to re-invoke the script with the options added to the environment.

In 7.0, grass.script.parser() invokes g.parser with the -s switch and
parses its output to initialise the options/flags dictionaries.

-- 
Glynn Clements <glynn at gclements.plus.com>


More information about the grass-dev mailing list