You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
assignee=Noneclosed_at=<Date2021-03-23.19:24:20.978>created_at=<Date2020-09-04.15:36:12.920>labels= ['tests', '3.10']
title='test.regrtest has way too many imports'updated_at=<Date2021-03-23.19:24:20.978>user='https://github.com/vstinner'
While investigating a crash on AIX (bpo-40068), I noticed that test_threading crashed because the test imports the logging module, and the logging has a bug on AIX on fork. I created an issue to reduce the number of imports made by "import test.support":
https://bugs.python.org/issue40275
I would prefer to better isolate tests: test_threading should only test the threading module, not the logging module.
Thanks to the hard work of Hai Shi, "import test.support" now imports only 37 modules instead of 171! He split the 3200 lines of Lib/test/support/init.py into new helper submodules: bytecode, import, threading, socket, etc. For example, TESTFN now comes from test.support.os_helper.
Sadly, test.regrtest.save_env still imports asyncio and multiprocessing, and so in practice, running any test using "python -m test (...)" still imports around 233 modules :-(
In general, it's nice to have the following 4 checks:
multiprocessing.process._dangling
asyncio.events._event_loop_policy
urllib.requests._url_tempfiles
urllib.requests._opener
The problem is that because of these checks, **any** unit test file of the 424 Python test files import asyncio, multiprocessing and urllib. As a result, **any** unit test starts with around 233 imported modules. We are far from an "unit" test, since many modules have side effects.
I wrote PR 22089 to remove these checks. "import test.libregrtest" is reduces from 233 to only 149 imports (on Linux), which is way better.
On Windows with current master, the baseline for running anything with 1 import (">>> import sys; len(sys.modules)") is 35 imported modules. Adding "import unittest" increases this to 80. What slightly puzzles me is that running
increases the number to 90. Perhaps unittest has delayed imports.
The current startup number for IDLE is 162, which can result in a cold startup of several seconds. I am thinking of trying to reduce this by delaying imports of modules that are not immediately used and might never be used.
For tests, I gather that side-effect issues are more important than startup time.
You could save/restore this data only when corresponded modules was imported, like it was done in clear_caches() in refleak.py. For example:
# Same for Process objectsdefget_multiprocessing_process__dangling(self):
multiprocessing_process=sys.modules.get('multiprocessing.process')
ifnotmultiprocessing_process:
returnset()
# Unjoined process objects can survive after process exitsmultiprocessing_process._cleanup()
# This copies the weakrefs without making any strong referencereturnmultiprocessing_process._dangling.copy()
defrestore_multiprocessing_process__dangling(self, saved):
multiprocessing_process=sys.modules.get('multiprocessing.process')
ifnotmultiprocessing_process:
returnmultiprocessing_process._dangling.clear()
multiprocessing_process._dangling.update(saved)
You could save/restore this data only when corresponded modules was imported, like it was done in clear_caches() in refleak.py.
It was my first idea, but some large modules like multiprocessing and asyncio are only imported by tested when the test file is imported, whereas save_environment() is called (enter) before the import in libregrtest.runtest.
Serhiy: "You could save/restore this data only when corresponded modules was imported, like it was done in clear_caches() in refleak.py."
That's a very good idea! I implemented it in PR 24934. But I modified runtest() to use *two* saved_test_environment instance. One before the test module is imported, one after. The one before is needed to check if the import itself has side effect, for example if the module body has side effect. The second is to check if running tests has side effect. The second one is more likely to have modules imported. The first one may miss some bugs, but IMO it's an acceptable trade-off.
Activity
vstinner commentedon Sep 4, 2020
Follow-up of bpo-40275.
While investigating a crash on AIX (bpo-40068), I noticed that test_threading crashed because the test imports the logging module, and the logging has a bug on AIX on fork. I created an issue to reduce the number of imports made by "import test.support":
https://bugs.python.org/issue40275
I would prefer to better isolate tests: test_threading should only test the threading module, not the logging module.
Thanks to the hard work of Hai Shi, "import test.support" now imports only 37 modules instead of 171! He split the 3200 lines of Lib/test/support/init.py into new helper submodules: bytecode, import, threading, socket, etc. For example, TESTFN now comes from test.support.os_helper.
Sadly, test.regrtest.save_env still imports asyncio and multiprocessing, and so in practice, running any test using "python -m test (...)" still imports around 233 modules :-(
I measured the number of imports done in practice using the following file, Lib/test/test_sys_modules.py:
----
master:
3.9:
3.5:
2.7:
vstinner commentedon Sep 4, 2020
If I hack test.libregrtest.runtest to not import test.libregrtest.save_env, test_sys_modules imports only 148 instead of 233 modules.
vstinner commentedon Sep 4, 2020
In general, it's nice to have the following 4 checks:
The problem is that because of these checks, **any** unit test file of the 424 Python test files import asyncio, multiprocessing and urllib. As a result, **any** unit test starts with around 233 imported modules. We are far from an "unit" test, since many modules have side effects.
I wrote PR 22089 to remove these checks. "import test.libregrtest" is reduces from 233 to only 149 imports (on Linux), which is way better.
vstinner commentedon Sep 4, 2020
With PR 22089, test_sys_modules.py of msg376374 imports 152 imports rather than 233. It's better than Python 2.7 which imports 170 modules!
terryjreedy commentedon Sep 5, 2020
On Windows with current master, the baseline for running anything with 1 import (">>> import sys; len(sys.modules)") is 35 imported modules. Adding "import unittest" increases this to 80. What slightly puzzles me is that runningincreases the number to 90. Perhaps unittest has delayed imports.
The current startup number for IDLE is 162, which can result in a cold startup of several seconds. I am thinking of trying to reduce this by delaying imports of modules that are not immediately used and might never be used.
For tests, I gather that side-effect issues are more important than startup time.
serhiy-storchaka commentedon Sep 5, 2020
You could save/restore this data only when corresponded modules was imported, like it was done in clear_caches() in refleak.py. For example:
vstinner commentedon Sep 6, 2020
It was my first idea, but some large modules like multiprocessing and asyncio are only imported by tested when the test file is imported, whereas save_environment() is called (enter) before the import in libregrtest.runtest.
serhiy-storchaka commentedon Sep 6, 2020
vstinner commentedon Mar 19, 2021
Serhiy: "You could save/restore this data only when corresponded modules was imported, like it was done in clear_caches() in refleak.py."
That's a very good idea! I implemented it in PR 24934. But I modified runtest() to use *two* saved_test_environment instance. One before the test module is imported, one after. The one before is needed to check if the import itself has side effect, for example if the module body has side effect. The second is to check if running tests has side effect. The second one is more likely to have modules imported. The first one may miss some bugs, but IMO it's an acceptable trade-off.
vstinner commentedon Mar 22, 2021
New changeset 532e063 by Victor Stinner in branch 'master':
bpo-41718: regrtest saved_test_environment avoids imports (GH-24934)
532e063
vstinner commentedon Mar 22, 2021
New changeset 10417dd by Victor Stinner in branch 'master':
bpo-41718: Reduce libregrtest runtest imports (GH-24980)
10417dd
vstinner commentedon Mar 23, 2021
New changeset 0473fb2 by Victor Stinner in branch 'master':
bpo-41718: libregrtest runtest avoids import_helper (GH-24983)
0473fb2
vstinner commentedon Mar 23, 2021
New changeset 30793e8 by Victor Stinner in branch 'master':
bpo-41718: Disable support.testresult XML output by default (GH-24982)
30793e8
vstinner commentedon Mar 23, 2021
New changeset 9feae41 by Victor Stinner in branch 'master':
bpo-41718: libregrtest avoids importing datetime (GH-24985)
9feae41
vstinner commentedon Mar 23, 2021
len(sys.modules) of msg376374 test_sys_modules:
The master branch imports 102 less modules than Python 3.9 (233 => 131)! Almost the half.
asyncio, logging, multiprocessing, etc. are no longer always imported by default.
vstinner commentedon Mar 23, 2021
New changeset d72e8d4 by Victor Stinner in branch 'master':
bpo-41718: subprocess imports grp and pwd on demand (GH-24987)
d72e8d4
vstinner commentedon Mar 23, 2021
New changeset bd9154a by Victor Stinner in branch 'master':
bpo-41718: runpy now imports pkgutil in functions (GH-24996)
bd9154a
vstinner commentedon Mar 23, 2021
New changeset cd27af7 by Victor Stinner in branch 'master':
bpo-41718: Update runpy startup time What's New (GH-24998)
cd27af7
vstinner commentedon Mar 23, 2021
Ok, the most important changes have been merged. Thanks everyone who helped on this large project! See also my summary email on python-dev:
https://mail.python.org/archives/list/python-dev@python.org/thread/I3OQTA3F66NQUN7CH2NHC5XZTO24QCIK/