mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +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