Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit db29e0f

Browse files
committed
SF patch #1035498: -m option to run a module as a script
(Contributed by Nick Coghlan.)
1 parent fb09f0e commit db29e0f

5 files changed

Lines changed: 109 additions & 11 deletions

File tree

Doc/tut/tut.tex

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,11 @@ \section{Invoking the Interpreter \label{invoking}}
205205
or other characters that are special to the shell, it is best to quote
206206
\var{command} in its entirety with double quotes.
207207

208+
Some Python modules are also useful as scripts. These can be invoked using
209+
\samp{\program{python} \programopt{-m} \var{module} [arg] ...}, which
210+
executes the source file for \var{module} as if you had spelled out its
211+
full name on the command line.
212+
208213
Note that there is a difference between \samp{python file} and
209214
\samp{python <file}. In the latter case, input requests from the
210215
program, such as calls to \function{input()} and \function{raw_input()}, are
@@ -229,9 +234,11 @@ \subsection{Argument Passing \label{argPassing}}
229234
an empty string. When the script name is given as \code{'-'} (meaning
230235
standard input), \code{sys.argv[0]} is set to \code{'-'}. When
231236
\programopt{-c} \var{command} is used, \code{sys.argv[0]} is set to
232-
\code{'-c'}. Options found after \programopt{-c} \var{command} are
233-
not consumed by the Python interpreter's option processing but left in
234-
\code{sys.argv} for the command to handle.
237+
\code{'-c'}. When \programopt{-m} \var{module} is used, \code{sys.argv[0]}
238+
is set to the full name of the located module. Options found after
239+
\programopt{-c} \var{command} or \programopt{-m} \var{module} are not consumed
240+
by the Python interpreter's option processing but left in \code{sys.argv} for
241+
the command or module to handle.
235242

236243
\subsection{Interactive Mode \label{interactive}}
237244

Include/import.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ PyAPI_FUNC(PyObject *) PyImport_ReloadModule(PyObject *m);
2121
PyAPI_FUNC(void) PyImport_Cleanup(void);
2222
PyAPI_FUNC(int) PyImport_ImportFrozenModule(char *);
2323

24+
PyAPI_FUNC(struct filedescr *) _PyImport_FindModule(
25+
const char *, PyObject *, char *, size_t, FILE **, PyObject **);
26+
PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr *);
27+
2428
PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *);
2529
PyAPI_FUNC(PyObject *)_PyImport_FixupExtension(char *, char *);
2630

Misc/NEWS

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.4 beta 1?
1212
Core and builtins
1313
-----------------
1414

15+
- Added a command line option, -m module, which searches sys.path for the
16+
module and then runs it. (Contributed by Nick Coghlan.)
17+
1518
- The bytecode optimizer now folds tuples of constants into a single
1619
constant.
1720

@@ -29,7 +32,9 @@ Extension modules
2932

3033
- ``collections.deque`` objects didn't play quite right with garbage
3134
collection, which could lead to a segfault in a release build, or
32-
an assert failure in a debug build.
35+
an assert failure in a debug build. Also, added overflow checks,
36+
better detection of mutation during iteration, and shielded deque
37+
comparisons from unusual subclass overrides of the __iter__() method.
3338

3439
Library
3540
-------

Modules/main.c

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Python.h"
44
#include "osdefs.h"
55
#include "compile.h" /* For CO_FUTURE_DIVISION */
6+
#include "import.h"
67

78
#ifdef __VMS
89
#include <unixlib.h>
@@ -33,7 +34,7 @@ static char **orig_argv;
3334
static int orig_argc;
3435

3536
/* command line options */
36-
#define BASE_OPTS "c:dEhiOQ:StuUvVW:xX"
37+
#define BASE_OPTS "c:dEhim:OQ:StuUvVW:xX"
3738

3839
#ifndef RISCOS
3940
#define PROGRAM_OPTS BASE_OPTS
@@ -47,7 +48,7 @@ extern int Py_RISCOSWimpFlag;
4748

4849
/* Short usage message (with %s for argv0) */
4950
static char *usage_line =
50-
"usage: %s [option] ... [-c cmd | file | -] [arg] ...\n";
51+
"usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
5152

5253
/* Long usage message, split into parts < 512 bytes */
5354
static char *usage_1 = "\
@@ -60,15 +61,16 @@ Options and arguments (and corresponding environment variables):\n\
6061
and force prompts, even if stdin does not appear to be a terminal\n\
6162
";
6263
static char *usage_2 = "\
64+
-m mod : run library module as a script (terminates option list)\n\
6365
-O : optimize generated bytecode (a tad; also PYTHONOPTIMIZE=x)\n\
6466
-OO : remove doc-strings in addition to the -O optimizations\n\
6567
-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
6668
-S : don't imply 'import site' on initialization\n\
6769
-t : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
6870
-u : unbuffered binary stdout and stderr (also PYTHONUNBUFFERED=x)\n\
69-
see man page for details on internal buffering relating to '-u'\n\
7071
";
7172
static char *usage_3 = "\
73+
see man page for details on internal buffering relating to '-u'\n\
7274
-v : verbose (trace import statements) (also PYTHONVERBOSE=x)\n\
7375
-V : print the Python version number and exit\n\
7476
-W arg : warning control (arg is action:message:category:module:lineno)\n\
@@ -130,6 +132,28 @@ static void RunStartupFile(PyCompilerFlags *cf)
130132
}
131133
}
132134

135+
/* Get the path to a top-level module */
136+
static struct filedescr * FindModule(const char *module,
137+
FILE **fp, char **filename)
138+
{
139+
struct filedescr *fdescr = NULL;
140+
*fp = NULL;
141+
*filename = malloc(MAXPATHLEN);
142+
143+
if (*filename == NULL)
144+
return NULL;
145+
146+
/* Find the actual module source code */
147+
fdescr = _PyImport_FindModule(module, NULL,
148+
*filename, MAXPATHLEN, fp, NULL);
149+
150+
if (fdescr == NULL) {
151+
free(*filename);
152+
*filename = NULL;
153+
}
154+
155+
return fdescr;
156+
}
133157

134158
/* Main program */
135159

@@ -140,6 +164,7 @@ Py_Main(int argc, char **argv)
140164
int sts;
141165
char *command = NULL;
142166
char *filename = NULL;
167+
char *module = NULL;
143168
FILE *fp = stdin;
144169
char *p;
145170
int inspect = 0;
@@ -177,6 +202,18 @@ Py_Main(int argc, char **argv)
177202
break;
178203
}
179204

205+
if (c == 'm') {
206+
/* -m is the last option; following arguments
207+
that look like options are left for the
208+
module to interpret. */
209+
module = malloc(strlen(_PyOS_optarg) + 2);
210+
if (module == NULL)
211+
Py_FatalError(
212+
"not enough memory to copy -m argument");
213+
strcpy(module, _PyOS_optarg);
214+
break;
215+
}
216+
180217
switch (c) {
181218

182219
case 'd':
@@ -289,7 +326,7 @@ Py_Main(int argc, char **argv)
289326
(p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
290327
unbuffered = 1;
291328

292-
if (command == NULL && _PyOS_optind < argc &&
329+
if (command == NULL && module == NULL && _PyOS_optind < argc &&
293330
strcmp(argv[_PyOS_optind], "-") != 0)
294331
{
295332
#ifdef __VMS
@@ -381,7 +418,7 @@ Py_Main(int argc, char **argv)
381418
Py_Initialize();
382419

383420
if (Py_VerboseFlag ||
384-
(command == NULL && filename == NULL && stdin_is_interactive)) {
421+
(command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
385422
fprintf(stderr, "Python %s on %s\n",
386423
Py_GetVersion(), Py_GetPlatform());
387424
if (!Py_NoSiteFlag)
@@ -394,9 +431,34 @@ Py_Main(int argc, char **argv)
394431
argv[_PyOS_optind] = "-c";
395432
}
396433

434+
if (module != NULL) {
435+
/* Backup _PyOS_optind and find the real file */
436+
struct filedescr *fdescr = NULL;
437+
_PyOS_optind--;
438+
if ((fdescr = FindModule(module, &fp, &filename))) {
439+
argv[_PyOS_optind] = filename;
440+
} else {
441+
fprintf(stderr, "%s: module %s not found\n",
442+
argv[0], module);
443+
return 2;
444+
}
445+
if (!fp) {
446+
fprintf(stderr,
447+
"%s: module %s has no associated file\n",
448+
argv[0], module);
449+
return 2;
450+
}
451+
if (!_PyImport_IsScript(fdescr)) {
452+
fprintf(stderr,
453+
"%s: module %s not usable as script\n (%s)\n",
454+
argv[0], module, filename);
455+
return 2;
456+
}
457+
}
458+
397459
PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
398460

399-
if ((inspect || (command == NULL && filename == NULL)) &&
461+
if ((inspect || (command == NULL && filename == NULL && module == NULL)) &&
400462
isatty(fileno(stdin))) {
401463
PyObject *v;
402464
v = PyImport_ImportModule("readline");
@@ -409,6 +471,10 @@ Py_Main(int argc, char **argv)
409471
if (command) {
410472
sts = PyRun_SimpleStringFlags(command, &cf) != 0;
411473
free(command);
474+
} else if (module) {
475+
sts = PyRun_AnyFileExFlags(fp, filename, 1, &cf) != 0;
476+
free(module);
477+
free(filename);
412478
}
413479
else {
414480
if (filename == NULL && stdin_is_interactive) {
@@ -431,7 +497,7 @@ Py_Main(int argc, char **argv)
431497
}
432498

433499
if (inspect && stdin_is_interactive &&
434-
(filename != NULL || command != NULL))
500+
(filename != NULL || command != NULL || module != NULL))
435501
/* XXX */
436502
sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
437503

Python/import.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,6 +1334,22 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf,
13341334
return fdp;
13351335
}
13361336

1337+
/* Helpers for main.c
1338+
* Find the source file corresponding to a named module
1339+
*/
1340+
struct filedescr *
1341+
_PyImport_FindModule(const char *name, PyObject *path, char *buf,
1342+
size_t buflen, FILE **p_fp, PyObject **p_loader)
1343+
{
1344+
return find_module((char *) name, (char *) name, path,
1345+
buf, buflen, p_fp, p_loader);
1346+
}
1347+
1348+
PyAPI_FUNC(int) _PyImport_IsScript(struct filedescr * fd)
1349+
{
1350+
return fd->type == PY_SOURCE || fd->type == PY_COMPILED;
1351+
}
1352+
13371353
/* case_ok(char* buf, int len, int namelen, char* name)
13381354
* The arguments here are tricky, best shown by example:
13391355
* /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0

0 commit comments

Comments
 (0)