[Python-checkins] bpo-44131: Py_FrozenMain() uses PyConfig_SetBytesArgv() (GH-26201)

vstinner webhook-mailer at python.org
Thu May 20 06:08:23 EDT 2021


https://github.com/python/cpython/commit/58a993957abec7e47acb20376d2753051fa75452
commit: 58a993957abec7e47acb20376d2753051fa75452
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2021-05-20T12:08:05+02:00
summary:

bpo-44131: Py_FrozenMain() uses PyConfig_SetBytesArgv() (GH-26201)

Moreover, Py_FrozenMain() relies on Py_InitializeFromConfig() to
handle the PYTHONUNBUFFERED environment variable and configure C
stdio streams like stdout (make the stream unbuffered).

files:
M Lib/test/test_embed.py
M Programs/test_frozenmain.h
M Programs/test_frozenmain.py
M Python/frozenmain.c

diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index c68a66270cfbd5..f4a18fdf5a566d 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1484,14 +1484,18 @@ def test_unicode_id_init(self):
     @unittest.skipIf(os.name == 'nt',
                      'Py_FrozenMain is not exported on Windows')
     def test_frozenmain(self):
-        out, err = self.run_embedded_interpreter("test_frozenmain")
-        exe = os.path.realpath('./argv0')
+        env = dict(os.environ)
+        env['PYTHONUNBUFFERED'] = '1'
+        out, err = self.run_embedded_interpreter("test_frozenmain", env=env)
+        executable = os.path.realpath('./argv0')
         expected = textwrap.dedent(f"""
             Frozen Hello World
             sys.argv ['./argv0', '-E', 'arg1', 'arg2']
             config program_name: ./argv0
-            config executable: {exe}
+            config executable: {executable}
             config use_environment: 1
+            config configure_c_stdio: 1
+            config buffered_stdio: 0
         """).lstrip()
         self.assertEqual(out, expected)
 
diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h
index e680b80e7ae8ac..a6c2e4296e6859 100644
--- a/Programs/test_frozenmain.h
+++ b/Programs/test_frozenmain.h
@@ -1,30 +1,28 @@
 // Auto-generated by Programs/freeze_test_frozenmain.py
 unsigned char M_test_frozenmain[] = {
     227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    0,4,0,0,0,64,0,0,0,115,106,0,0,0,100,0,
+    0,7,0,0,0,64,0,0,0,115,86,0,0,0,100,0,
     100,1,108,0,90,0,100,0,100,1,108,1,90,1,101,2,
     100,2,131,1,1,0,101,2,100,3,101,0,106,3,131,2,
-    1,0,101,1,160,4,161,0,100,4,25,0,90,5,101,2,
-    100,5,101,5,100,6,25,0,155,0,157,2,131,1,1,0,
-    101,2,100,7,101,5,100,8,25,0,155,0,157,2,131,1,
-    1,0,101,2,100,9,101,5,100,10,25,0,155,0,157,2,
-    131,1,1,0,100,1,83,0,41,11,233,0,0,0,0,78,
-    122,18,70,114,111,122,101,110,32,72,101,108,108,111,32,87,
-    111,114,108,100,122,8,115,121,115,46,97,114,103,118,218,6,
-    99,111,110,102,105,103,122,21,99,111,110,102,105,103,32,112,
-    114,111,103,114,97,109,95,110,97,109,101,58,32,90,12,112,
-    114,111,103,114,97,109,95,110,97,109,101,122,19,99,111,110,
-    102,105,103,32,101,120,101,99,117,116,97,98,108,101,58,32,
-    218,10,101,120,101,99,117,116,97,98,108,101,122,24,99,111,
-    110,102,105,103,32,117,115,101,95,101,110,118,105,114,111,110,
-    109,101,110,116,58,32,90,15,117,115,101,95,101,110,118,105,
-    114,111,110,109,101,110,116,41,6,218,3,115,121,115,90,17,
-    95,116,101,115,116,105,110,116,101,114,110,97,108,99,97,112,
-    105,218,5,112,114,105,110,116,218,4,97,114,103,118,90,11,
-    103,101,116,95,99,111,110,102,105,103,115,114,2,0,0,0,
-    169,0,114,7,0,0,0,114,7,0,0,0,250,18,116,101,
-    115,116,95,102,114,111,122,101,110,109,97,105,110,46,112,121,
-    218,8,60,109,111,100,117,108,101,62,1,0,0,0,115,16,
-    0,0,0,8,3,8,1,8,2,12,1,12,1,18,1,18,
-    1,22,1,243,0,0,0,0,
+    1,0,101,1,160,4,161,0,100,4,25,0,90,5,100,5,
+    68,0,93,14,90,6,101,2,100,6,101,6,155,0,100,7,
+    101,5,101,6,25,0,155,0,157,4,131,1,1,0,113,26,
+    100,1,83,0,41,8,233,0,0,0,0,78,122,18,70,114,
+    111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100,
+    122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102,
+    105,103,41,5,90,12,112,114,111,103,114,97,109,95,110,97,
+    109,101,218,10,101,120,101,99,117,116,97,98,108,101,90,15,
+    117,115,101,95,101,110,118,105,114,111,110,109,101,110,116,90,
+    17,99,111,110,102,105,103,117,114,101,95,99,95,115,116,100,
+    105,111,90,14,98,117,102,102,101,114,101,100,95,115,116,100,
+    105,111,122,7,99,111,110,102,105,103,32,122,2,58,32,41,
+    7,218,3,115,121,115,90,17,95,116,101,115,116,105,110,116,
+    101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116,
+    218,4,97,114,103,118,90,11,103,101,116,95,99,111,110,102,
+    105,103,115,114,2,0,0,0,218,3,107,101,121,169,0,114,
+    8,0,0,0,114,8,0,0,0,250,18,116,101,115,116,95,
+    102,114,111,122,101,110,109,97,105,110,46,112,121,218,8,60,
+    109,111,100,117,108,101,62,1,0,0,0,115,16,0,0,0,
+    8,3,8,1,8,2,12,1,12,1,8,1,26,7,4,249,
+    243,0,0,0,0,
 };
diff --git a/Programs/test_frozenmain.py b/Programs/test_frozenmain.py
index 928b9ea816accb..53f5fd676a2d15 100644
--- a/Programs/test_frozenmain.py
+++ b/Programs/test_frozenmain.py
@@ -7,6 +7,11 @@
 print("Frozen Hello World")
 print("sys.argv", sys.argv)
 config = _testinternalcapi.get_configs()['config']
-print(f"config program_name: {config['program_name']}")
-print(f"config executable: {config['executable']}")
-print(f"config use_environment: {config['use_environment']}")
+for key in (
+    'program_name',
+    'executable',
+    'use_environment',
+    'configure_c_stdio',
+    'buffered_stdio',
+):
+    print(f"config {key}: {config[key]}")
diff --git a/Python/frozenmain.c b/Python/frozenmain.c
index c3104dae449771..8743e082b4ff8f 100644
--- a/Python/frozenmain.c
+++ b/Python/frozenmain.c
@@ -20,74 +20,28 @@ Py_FrozenMain(int argc, char **argv)
         Py_ExitStatusException(status);
     }
 
-    const char *p;
-    int i, n, sts = 1;
-    int inspect = 0;
-    int unbuffered = 0;
-    char *oldloc = NULL;
-    wchar_t **argv_copy = NULL;
-    /* We need a second copies, as Python might modify the first one. */
-    wchar_t **argv_copy2 = NULL;
-
-    if (argc > 0) {
-        argv_copy = PyMem_RawMalloc(sizeof(wchar_t*) * argc);
-        argv_copy2 = PyMem_RawMalloc(sizeof(wchar_t*) * argc);
-        if (!argv_copy || !argv_copy2) {
-            fprintf(stderr, "out of memory\n");
-            goto error;
-        }
-    }
-
     PyConfig config;
     PyConfig_InitPythonConfig(&config);
-    config.pathconfig_warnings = 0;   /* Suppress errors from getpath.c */
-
-    if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') {
-        inspect = 1;
-    }
-    if ((p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') {
-        unbuffered = 1;
-    }
-
-    if (unbuffered) {
-        setbuf(stdin, (char *)NULL);
-        setbuf(stdout, (char *)NULL);
-        setbuf(stderr, (char *)NULL);
-    }
+    // Suppress errors from getpath.c
+    config.pathconfig_warnings = 0;
+    // Don't parse command line options like -E
+    config.parse_argv = 0;
 
-    oldloc = _PyMem_RawStrdup(setlocale(LC_ALL, NULL));
-    if (!oldloc) {
-        fprintf(stderr, "out of memory\n");
-        goto error;
+    status = PyConfig_SetBytesArgv(&config, argc, argv);
+    if (PyStatus_Exception(status)) {
+        PyConfig_Clear(&config);
+        Py_ExitStatusException(status);
     }
 
-    setlocale(LC_ALL, "");
-    for (i = 0; i < argc; i++) {
-        argv_copy[i] = Py_DecodeLocale(argv[i], NULL);
-        argv_copy2[i] = argv_copy[i];
-        if (!argv_copy[i]) {
-            fprintf(stderr,
-                    "Unable to decode the command line argument #%i\n",
-                    i + 1);
-            argc = i;
-            goto error;
-        }
+    const char *p;
+    int inspect = 0;
+    if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') {
+        inspect = 1;
     }
-    setlocale(LC_ALL, oldloc);
-    PyMem_RawFree(oldloc);
-    oldloc = NULL;
 
 #ifdef MS_WINDOWS
     PyInitFrozenExtensions();
 #endif /* MS_WINDOWS */
-    if (argc >= 1) {
-        status = PyConfig_SetString(&config, &config.program_name,
-                                    argv_copy[0]);
-        if (PyStatus_Exception(status)) {
-            PyConfig_Clear(&config);
-            Py_ExitStatusException(status);
-        }
-    }
 
     status = Py_InitializeFromConfig(&config);
     PyConfig_Clear(&config);
@@ -104,9 +58,8 @@ Py_FrozenMain(int argc, char **argv)
                 Py_GetVersion(), Py_GetCopyright());
     }
 
-    PySys_SetArgv(argc, argv_copy);
-
-    n = PyImport_ImportFrozenModule("__main__");
+    int sts = 1;
+    int n = PyImport_ImportFrozenModule("__main__");
     if (n == 0) {
         Py_FatalError("the __main__ module is not frozen");
     }
@@ -128,14 +81,5 @@ Py_FrozenMain(int argc, char **argv)
     if (Py_FinalizeEx() < 0) {
         sts = 120;
     }
-
-error:
-    PyMem_RawFree(argv_copy);
-    if (argv_copy2) {
-        for (i = 0; i < argc; i++)
-            PyMem_RawFree(argv_copy2[i]);
-        PyMem_RawFree(argv_copy2);
-    }
-    PyMem_RawFree(oldloc);
     return sts;
 }



More information about the Python-checkins mailing list