mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	SF patch #1035498: -m option to run a module as a script
(Contributed by Nick Coghlan.)
This commit is contained in:
		
							parent
							
								
									fb09f0e85c
								
							
						
					
					
						commit
						db29e0fe8c
					
				
					 5 changed files with 109 additions and 11 deletions
				
			
		| 
						 | 
					@ -205,6 +205,11 @@ executes the statement(s) in \var{command}, analogous to the shell's
 | 
				
			||||||
or other characters that are special to the shell, it is best to quote 
 | 
					or other characters that are special to the shell, it is best to quote 
 | 
				
			||||||
\var{command} in its entirety with double quotes.
 | 
					\var{command} in its entirety with double quotes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some Python modules are also useful as scripts.  These can be invoked using
 | 
				
			||||||
 | 
					\samp{\program{python} \programopt{-m} \var{module} [arg] ...}, which
 | 
				
			||||||
 | 
					executes the source file for \var{module} as if you had spelled out its
 | 
				
			||||||
 | 
					full name on the command line.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note that there is a difference between \samp{python file} and
 | 
					Note that there is a difference between \samp{python file} and
 | 
				
			||||||
\samp{python <file}.  In the latter case, input requests from the
 | 
					\samp{python <file}.  In the latter case, input requests from the
 | 
				
			||||||
program, such as calls to \function{input()} and \function{raw_input()}, are
 | 
					program, such as calls to \function{input()} and \function{raw_input()}, are
 | 
				
			||||||
| 
						 | 
					@ -229,9 +234,11 @@ one; when no script and no arguments are given, \code{sys.argv[0]} is
 | 
				
			||||||
an empty string.  When the script name is given as \code{'-'} (meaning 
 | 
					an empty string.  When the script name is given as \code{'-'} (meaning 
 | 
				
			||||||
standard input), \code{sys.argv[0]} is set to \code{'-'}.  When
 | 
					standard input), \code{sys.argv[0]} is set to \code{'-'}.  When
 | 
				
			||||||
\programopt{-c} \var{command} is used, \code{sys.argv[0]} is set to
 | 
					\programopt{-c} \var{command} is used, \code{sys.argv[0]} is set to
 | 
				
			||||||
\code{'-c'}.  Options found after \programopt{-c} \var{command} are
 | 
					\code{'-c'}.  When \programopt{-m} \var{module} is used, \code{sys.argv[0]} 
 | 
				
			||||||
not consumed by the Python interpreter's option processing but left in
 | 
					is set to the full name of the located module.  Options found after 
 | 
				
			||||||
\code{sys.argv} for the command to handle.
 | 
					\programopt{-c} \var{command} or \programopt{-m} \var{module} are not consumed 
 | 
				
			||||||
 | 
					by the Python interpreter's option processing but left in \code{sys.argv} for 
 | 
				
			||||||
 | 
					the command or module to handle.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
\subsection{Interactive Mode \label{interactive}}
 | 
					\subsection{Interactive Mode \label{interactive}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,10 @@ PyAPI_FUNC(PyObject *) PyImport_ReloadModule(PyObject *m);
 | 
				
			||||||
PyAPI_FUNC(void) PyImport_Cleanup(void);
 | 
					PyAPI_FUNC(void) PyImport_Cleanup(void);
 | 
				
			||||||
PyAPI_FUNC(int) PyImport_ImportFrozenModule(char *);
 | 
					PyAPI_FUNC(int) PyImport_ImportFrozenModule(char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyAPI_FUNC(struct filedescr *) _PyImport_FindModule(
 | 
				
			||||||
 | 
						const char *, PyObject *, char *, size_t, FILE **, PyObject **);
 | 
				
			||||||
 | 
					PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *);
 | 
					PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *);
 | 
				
			||||||
PyAPI_FUNC(PyObject *)_PyImport_FixupExtension(char *, char *);
 | 
					PyAPI_FUNC(PyObject *)_PyImport_FixupExtension(char *, char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,9 @@ What's New in Python 2.4 beta 1?
 | 
				
			||||||
Core and builtins
 | 
					Core and builtins
 | 
				
			||||||
-----------------
 | 
					-----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Added a command line option, -m module, which searches sys.path for the
 | 
				
			||||||
 | 
					  module and then runs it.  (Contributed by Nick Coghlan.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- The bytecode optimizer now folds tuples of constants into a single
 | 
					- The bytecode optimizer now folds tuples of constants into a single
 | 
				
			||||||
  constant.
 | 
					  constant.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +32,9 @@ Extension modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- ``collections.deque`` objects didn't play quite right with garbage
 | 
					- ``collections.deque`` objects didn't play quite right with garbage
 | 
				
			||||||
  collection, which could lead to a segfault in a release build, or
 | 
					  collection, which could lead to a segfault in a release build, or
 | 
				
			||||||
  an assert failure in a debug build.
 | 
					  an assert failure in a debug build.  Also, added overflow checks,
 | 
				
			||||||
 | 
					  better detection of mutation during iteration, and shielded deque
 | 
				
			||||||
 | 
					  comparisons from unusual subclass overrides of the __iter__() method.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Library
 | 
					Library
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
#include "Python.h"
 | 
					#include "Python.h"
 | 
				
			||||||
#include "osdefs.h"
 | 
					#include "osdefs.h"
 | 
				
			||||||
#include "compile.h" /* For CO_FUTURE_DIVISION */
 | 
					#include "compile.h" /* For CO_FUTURE_DIVISION */
 | 
				
			||||||
 | 
					#include "import.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __VMS
 | 
					#ifdef __VMS
 | 
				
			||||||
#include <unixlib.h>
 | 
					#include <unixlib.h>
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ static char **orig_argv;
 | 
				
			||||||
static int  orig_argc;
 | 
					static int  orig_argc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* command line options */
 | 
					/* command line options */
 | 
				
			||||||
#define BASE_OPTS "c:dEhiOQ:StuUvVW:xX"
 | 
					#define BASE_OPTS "c:dEhim:OQ:StuUvVW:xX"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef RISCOS
 | 
					#ifndef RISCOS
 | 
				
			||||||
#define PROGRAM_OPTS BASE_OPTS
 | 
					#define PROGRAM_OPTS BASE_OPTS
 | 
				
			||||||
| 
						 | 
					@ -47,7 +48,7 @@ extern int Py_RISCOSWimpFlag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Short usage message (with %s for argv0) */
 | 
					/* Short usage message (with %s for argv0) */
 | 
				
			||||||
static char *usage_line =
 | 
					static char *usage_line =
 | 
				
			||||||
"usage: %s [option] ... [-c cmd | file | -] [arg] ...\n";
 | 
					"usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Long usage message, split into parts < 512 bytes */
 | 
					/* Long usage message, split into parts < 512 bytes */
 | 
				
			||||||
static char *usage_1 = "\
 | 
					static char *usage_1 = "\
 | 
				
			||||||
| 
						 | 
					@ -60,15 +61,16 @@ Options and arguments (and corresponding environment variables):\n\
 | 
				
			||||||
         and force prompts, even if stdin does not appear to be a terminal\n\
 | 
					         and force prompts, even if stdin does not appear to be a terminal\n\
 | 
				
			||||||
";
 | 
					";
 | 
				
			||||||
static char *usage_2 = "\
 | 
					static char *usage_2 = "\
 | 
				
			||||||
 | 
					-m mod : run library module as a script (terminates option list)\n\
 | 
				
			||||||
-O     : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n\
 | 
					-O     : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n\
 | 
				
			||||||
-OO    : remove doc-strings in addition to the -O optimizations\n\
 | 
					-OO    : remove doc-strings in addition to the -O optimizations\n\
 | 
				
			||||||
-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
 | 
					-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
 | 
				
			||||||
-S     : don't imply 'import site' on initialization\n\
 | 
					-S     : don't imply 'import site' on initialization\n\
 | 
				
			||||||
-t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
 | 
					-t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
 | 
				
			||||||
-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)\n\
 | 
					-u     : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)\n\
 | 
				
			||||||
         see man page for details on internal buffering relating to '-u'\n\
 | 
					 | 
				
			||||||
";
 | 
					";
 | 
				
			||||||
static char *usage_3 = "\
 | 
					static char *usage_3 = "\
 | 
				
			||||||
 | 
					         see man page for details on internal buffering relating to '-u'\n\
 | 
				
			||||||
-v     : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
 | 
					-v     : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
 | 
				
			||||||
-V     : print the Python version number and exit\n\
 | 
					-V     : print the Python version number and exit\n\
 | 
				
			||||||
-W arg : warning control (arg is action:message:category:module:lineno)\n\
 | 
					-W arg : warning control (arg is action:message:category:module:lineno)\n\
 | 
				
			||||||
| 
						 | 
					@ -130,6 +132,28 @@ static void RunStartupFile(PyCompilerFlags *cf)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get the path to a top-level module */
 | 
				
			||||||
 | 
					static struct filedescr * FindModule(const char *module,
 | 
				
			||||||
 | 
									     FILE **fp, char **filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct filedescr *fdescr = NULL;
 | 
				
			||||||
 | 
						*fp = NULL;
 | 
				
			||||||
 | 
						*filename = malloc(MAXPATHLEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (*filename == NULL)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Find the actual module source code */
 | 
				
			||||||
 | 
						fdescr = _PyImport_FindModule(module, NULL,
 | 
				
			||||||
 | 
										*filename, MAXPATHLEN, fp, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fdescr == NULL) {
 | 
				
			||||||
 | 
							free(*filename);
 | 
				
			||||||
 | 
							*filename = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fdescr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Main program */
 | 
					/* Main program */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +164,7 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
	int sts;
 | 
						int sts;
 | 
				
			||||||
	char *command = NULL;
 | 
						char *command = NULL;
 | 
				
			||||||
	char *filename = NULL;
 | 
						char *filename = NULL;
 | 
				
			||||||
 | 
						char *module = NULL;
 | 
				
			||||||
	FILE *fp = stdin;
 | 
						FILE *fp = stdin;
 | 
				
			||||||
	char *p;
 | 
						char *p;
 | 
				
			||||||
	int inspect = 0;
 | 
						int inspect = 0;
 | 
				
			||||||
| 
						 | 
					@ -177,6 +202,18 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (c == 'm') {
 | 
				
			||||||
 | 
								/* -m is the last option; following arguments
 | 
				
			||||||
 | 
								   that look like options are left for the
 | 
				
			||||||
 | 
								   module to interpret. */
 | 
				
			||||||
 | 
								module = malloc(strlen(_PyOS_optarg) + 2);
 | 
				
			||||||
 | 
								if (module == NULL)
 | 
				
			||||||
 | 
									Py_FatalError(
 | 
				
			||||||
 | 
									   "not enough memory to copy -m argument");
 | 
				
			||||||
 | 
								strcpy(module, _PyOS_optarg);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (c) {
 | 
							switch (c) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case 'd':
 | 
							case 'd':
 | 
				
			||||||
| 
						 | 
					@ -289,7 +326,7 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
	    (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
 | 
						    (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
 | 
				
			||||||
		unbuffered = 1;
 | 
							unbuffered = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (command == NULL && _PyOS_optind < argc &&
 | 
						if (command == NULL && module == NULL && _PyOS_optind < argc &&
 | 
				
			||||||
	    strcmp(argv[_PyOS_optind], "-") != 0)
 | 
						    strcmp(argv[_PyOS_optind], "-") != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
#ifdef __VMS
 | 
					#ifdef __VMS
 | 
				
			||||||
| 
						 | 
					@ -381,7 +418,7 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
	Py_Initialize();
 | 
						Py_Initialize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (Py_VerboseFlag ||
 | 
						if (Py_VerboseFlag ||
 | 
				
			||||||
	    (command == NULL && filename == NULL && stdin_is_interactive)) {
 | 
						    (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
 | 
				
			||||||
		fprintf(stderr, "Python %s on %s\n",
 | 
							fprintf(stderr, "Python %s on %s\n",
 | 
				
			||||||
			Py_GetVersion(), Py_GetPlatform());
 | 
								Py_GetVersion(), Py_GetPlatform());
 | 
				
			||||||
 		if (!Py_NoSiteFlag)
 | 
					 		if (!Py_NoSiteFlag)
 | 
				
			||||||
| 
						 | 
					@ -394,9 +431,34 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
		argv[_PyOS_optind] = "-c";
 | 
							argv[_PyOS_optind] = "-c";
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (module != NULL) {
 | 
				
			||||||
 | 
							/* Backup _PyOS_optind and find the real file */
 | 
				
			||||||
 | 
					                struct filedescr *fdescr = NULL;
 | 
				
			||||||
 | 
							_PyOS_optind--;
 | 
				
			||||||
 | 
							if ((fdescr = FindModule(module, &fp, &filename))) {
 | 
				
			||||||
 | 
								argv[_PyOS_optind] = filename;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fprintf(stderr, "%s: module %s not found\n",
 | 
				
			||||||
 | 
									argv[0], module);
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!fp) {
 | 
				
			||||||
 | 
								fprintf(stderr,
 | 
				
			||||||
 | 
									"%s: module %s has no associated file\n",
 | 
				
			||||||
 | 
									argv[0], module);
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if (!_PyImport_IsScript(fdescr)) {
 | 
				
			||||||
 | 
								fprintf(stderr,
 | 
				
			||||||
 | 
									"%s: module %s not usable as script\n  (%s)\n",
 | 
				
			||||||
 | 
									argv[0], module, filename);
 | 
				
			||||||
 | 
								return 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
 | 
						PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((inspect || (command == NULL && filename == NULL)) &&
 | 
						if ((inspect || (command == NULL && filename == NULL && module == NULL)) &&
 | 
				
			||||||
	    isatty(fileno(stdin))) {
 | 
						    isatty(fileno(stdin))) {
 | 
				
			||||||
		PyObject *v;
 | 
							PyObject *v;
 | 
				
			||||||
		v = PyImport_ImportModule("readline");
 | 
							v = PyImport_ImportModule("readline");
 | 
				
			||||||
| 
						 | 
					@ -409,6 +471,10 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
	if (command) {
 | 
						if (command) {
 | 
				
			||||||
		sts = PyRun_SimpleStringFlags(command, &cf) != 0;
 | 
							sts = PyRun_SimpleStringFlags(command, &cf) != 0;
 | 
				
			||||||
		free(command);
 | 
							free(command);
 | 
				
			||||||
 | 
						} else if (module) {
 | 
				
			||||||
 | 
							sts = PyRun_AnyFileExFlags(fp, filename, 1, &cf) != 0;
 | 
				
			||||||
 | 
							free(module);
 | 
				
			||||||
 | 
							free(filename);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		if (filename == NULL && stdin_is_interactive) {
 | 
							if (filename == NULL && stdin_is_interactive) {
 | 
				
			||||||
| 
						 | 
					@ -431,7 +497,7 @@ Py_Main(int argc, char **argv)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (inspect && stdin_is_interactive &&
 | 
						if (inspect && stdin_is_interactive &&
 | 
				
			||||||
	    (filename != NULL || command != NULL))
 | 
						    (filename != NULL || command != NULL || module != NULL))
 | 
				
			||||||
		/* XXX */
 | 
							/* XXX */
 | 
				
			||||||
		sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
 | 
							sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1334,6 +1334,22 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf,
 | 
				
			||||||
	return fdp;
 | 
						return fdp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Helpers for main.c
 | 
				
			||||||
 | 
					 *  Find the source file corresponding to a named module
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct filedescr *
 | 
				
			||||||
 | 
					_PyImport_FindModule(const char *name, PyObject *path, char *buf,
 | 
				
			||||||
 | 
						    size_t buflen, FILE **p_fp, PyObject **p_loader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return find_module((char *) name, (char *) name, path,
 | 
				
			||||||
 | 
								   buf, buflen, p_fp, p_loader);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr * fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return fd->type == PY_SOURCE || fd->type == PY_COMPILED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* case_ok(char* buf, int len, int namelen, char* name)
 | 
					/* case_ok(char* buf, int len, int namelen, char* name)
 | 
				
			||||||
 * The arguments here are tricky, best shown by example:
 | 
					 * The arguments here are tricky, best shown by example:
 | 
				
			||||||
 *    /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0
 | 
					 *    /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue