-
-
Notifications
You must be signed in to change notification settings - Fork 31.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PYTHONOPTIMIZE ignored in 3.7.0 when using custom launcher #78428
Comments
Attached is a very basic launcher for python scripts. This script works as expected in Python 3.6, but not in 3.7.0. In particular, the launcher sets the environment variable PYTHONOPTIMIZE before calling Py_Initialize and that setting is ignored. I haven't tried testing with the tip of the tree yet. |
This feels like a duplicate of https://bugs.python.org/issue31845 (see d7ac061 ) Is this definitely with the 3.7.0 release, or is it potentially with one of the earlier alphas before that fix was applied? |
Ah, wait - I see a relevant difference: the test case for bpo-31845 uses Py_Main, *not* Py_Initialize (since it's a command line test, not an embedding test). That means it's currently possible for the sequence of operations in Line 913 in 7cbde0e
|
Comparing to Python 3.6, we can see that the code to update the C global flags from the environment variables used to live directly in _PyInitializeEx_Private: Line 305 in 9d85856
In Python 3.7 that section (https://github.com/python/cpython/blob/3.7/Python/pylifecycle.c#L913 ) currently calls _PyCoreConfig_Read instead, which *only* updates the config struct - it doesn't update the C level global variables. By contrast, Py_Main eventually calls Line 1394 in 7cbde0e
|
Next steps:
|
Ned, I think we should consider this a release blocker for 3.7.1 |
This seems closely related to the work Victor is already pursuing to resolve bpo-34170 for Python 3.8 (e.g. 56b29b6 ). The bpo-34170 changes are more invasive than we'd like for a maintenance release, but it would be preferable to keep at least any new Python 3.7 test cases somewhat aligned with their Python 3.8 counterparts. |
I'm at the EuroPython sprints and currently working on a testcase for this. Should be a nice way to get back into actively contributing to CPython :-) |
FYI: I've filed bpo-34255 while working on this, test_embed assumes that you're building in the source directory (which I usually don't do). |
Interesting... pylifecycle.c uses code in main.c, I hadn't expected that. If I've read the code correctly Py_Initialize won't look at PYTHONOPTIMZE at all (and other environment variables that have a command-line equivalent). Those are read in main.c:cmdline_get_env_flags, which is only called (indirectly) from Py_Main and _Py_UnixMain. I'm note sure what's the correct solution for this.
|
I've created a pull request that seems to work properly, although I am not entirely sure that this is the right way to fix this. As I mentioned in the pull request I created it against the 3.7 branch because of bpo-34170, but would happily rebase it for master. |
I believe Victor is at the EuroPython sprints as well, so if I'm right about that, I think the best option would be for the two of you to work out a resolution for 3.7.1 in person that at least keeps the test suites reasonably consistent, even if the implementations have diverged (the new tests already added for bpo-34170 were the main reason I stopped working on my initial patch for this). And agreed on fixing the current dependency inversion between pylifecycle and the py_main code - the functions needed by both Py_Main and Py_Initialize should be migrated down the stack into pylifecycle as part of the bpo-34170 work. |
I first proposed to backport all code from master: But I'm not sure that it's a good idea, since I made *many* changes in the master branch since 3.7... I even added more files, and the _PyCoreConfig API is going to change anyway... So I wrote a simpler PR 8659 which backports unit tests, adapt them for Python 3.7, and fix this issue: PYTHONOPTIMIZE and other environment variables and now read by Py_Initialize(), not only by Py_Main(). |
I tested manually attached t.c with PR 8659: I get optimize=2 as expected. Full output: sys.flags(debug=0, inspect=0, interactive=0, optimize=2, dont_write_bytecode=0, no_user_site=0, no_site=0, ignore_environment=0, verbose=0, bytes_warning=0, quiet=0, hash_randomization=1, isolated=0, dev_mode=False, utf8_mode=1) |
The PR works for me as well, and looks ok to me. |
On my PR, Nick Coghlan wrote: "We may want to tweak the porting note in What's New, as I believe this may read more environment variables at init time than the interpreter did previously, so embedding applications that want more complete control may now need to set Py_IgnoreEnvironmentFlag when they could previously get by without it." I'm not sure about this, since it's really a bug of Python 3.7.0 and it's now fixed. I let you decide if the issue should be closed or not, I leave it open. |
My comment wasn't about the 3.7.0 -> 3.7.1 fix, but rather about the fact that I suspect that 3.7.1 is now going to respect some environment variables in this case that 3.6.x ignored. I don't know for sure though, since we didn't have a test case for this until you wrote one. So I was thinking we could include a porting note along the lines of: ===============
That note then serves two purposes:
|
PR 9223 adds Nick's proposed wording to the 3.7 What's News. |
I'm not aware of the Python 3.6 issue ("ill-defined"): which env vars were not properly handled? |
I've merged Nick's suggested porting note so I'm going to remove the "release blocker" status. Can we also close this now? |
The "ill-defined" in Python 3.6 relates to the fact that we never actually defined or tested which environment variables were read by Py_Main and which ones were read by Py_Initialize, since the majority of our tests only covered Py_Main (by launching a full Python subprocess). Thus the only way to find out which environment variables fell into which category would be to read the Python 3.6 source code. That's technically still the case for Python 3.7, but Victor's done some excellent refactoring work so it's much clearer in the code which vars may be updated if Py_Initialize is run a second time. |
Oh ok, I see. Thanks for the explanation.
Well, for me the most important part is not the code, but tests. test_embed currently tests the following environment variables: static void test_init_env_putenvs(void)
{
putenv("PYTHONHASHSEED=42");
putenv("PYTHONMALLOC=malloc_debug");
putenv("PYTHONTRACEMALLOC=2");
putenv("PYTHONPROFILEIMPORTTIME=1");
putenv("PYTHONMALLOCSTATS=1");
putenv("PYTHONUTF8=1");
putenv("PYTHONVERBOSE=1");
putenv("PYTHONINSPECT=1");
putenv("PYTHONOPTIMIZE=2");
putenv("PYTHONDONTWRITEBYTECODE=1");
putenv("PYTHONUNBUFFERED=1");
putenv("PYTHONNOUSERSITE=1");
putenv("PYTHONFAULTHANDLER=1");
putenv("PYTHONDEVMODE=1");
/* FIXME: test PYTHONWARNINGS */
/* FIXME: test PYTHONEXECUTABLE */
/* FIXME: test PYTHONHOME */
/* FIXME: test PYTHONDEBUG */
/* FIXME: test PYTHONDUMPREFS */
/* FIXME: test PYTHONCOERCECLOCALE */
/* FIXME: test PYTHONPATH */
} As you can see, the test suite is not complete yet. But since the tests are there, it shouldn't be hard to extend the test suite. test_embed has InitConfigTests in 3.7 and master branches. I'm not interested to backport these tests to 3.6. I modified Python initialization deeply in 3.7, and the status of the code in 3.6 is "undefined". I don't think that it's worth it to backport these tests to 2.7 or 3.6. I success to focus on the master branch where we want to finish the implementation of the PEP-432 which should provide a better *public* API for that. |
Yep, exactly - things are much improved already, thanks primarily to your work, and it seems likely they'll be even further improved by the time 3.8.0 comes around :) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: