-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Drop Python 2.7 support #2480
Comments
Good call @giampaolo. And really cool to see the stats of 2.7 dropping to 0.36% :). I think pretty much all libraries (even those that for good reasons kept Python 2.7 compatibility) is one of the last things to finally announce Python 2.7 a "dead snake". There ae still some industries that have some 2.7 codebase (anecdotally gaming industry is apparently one of them to my surprise), but it only makes sense to shift the burden of maintaining the code to them rather than having maintainers of the open-source projects to do it. If anyone wants still to use Python 2.7 and use psutil - even if they will need new features, it should be on them to backport anything they need - not you. |
As part of the dropping of Python 2.7 support (#2480), we can now take advantage of chained exceptions machinery (`raise x from y` and `raise x from None`). In practical terms, this is what changes: # Shorter tracebacks When adding the full traceback info adds no value, we now shorten tracebacks if `raise X from None`. A similar (hackish) attempt was made in 633d8019, when we were still stuck with Python 2. The notable example is passing a PID that does not exist to the `Process` class: ```python psutil.Process(333) ``` Before we got: ``` Traceback (most recent call last): File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1647, in wrapper return fun(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_common.py", line 464, in wrapper raise err from None File "/home/giampaolo/svn/psutil/psutil/_common.py", line 462, in wrapper return fun(self) ^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1713, in _parse_stat_file data = bcat(f"{self._procfs_path}/{self.pid}/stat") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_common.py", line 794, in bcat return cat(fname, fallback=fallback, _open=open_binary) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_common.py", line 782, in cat with _open(fname) as f: ^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_common.py", line 746, in open_binary return open(fname, "rb", buffering=FILE_READ_BUFFER_SIZE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: '/proc/341244/stat' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 350, in _init self._ident = self._get_ident() ^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 391, in _get_ident return (self.pid, self.create_time()) ^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 773, in create_time self._create_time = self._proc.create_time() ^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1647, in wrapper return fun(self, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1885, in create_time ctime = float(self._parse_stat_file()['create_time']) ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1659, in wrapper raise NoSuchProcess(pid, name) from err psutil.NoSuchProcess: process no longer exists (pid=341244) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/giampaolo/svn/psutil/foo.py", line 5, in <module> psutil.Process(341244) File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 317, in __init__ self._init(pid) File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 363, in _init raise NoSuchProcess(pid, msg=msg) psutil.NoSuchProcess: process PID not found (pid=341244) ``` Now we get: ``` Traceback (most recent call last): File "/home/giampaolo/svn/psutil/foo.py", line 5, in <module> psutil.Process(341244) File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 317, in __init__ self._init(pid) File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 363, in _init raise NoSuchProcess(pid, msg=msg) from None psutil.NoSuchProcess: process PID not found (pid=341244) ``` # Different wording for "translated" exceptions By "translated" I mean psutil's `NoSuchProcess`, `ZombieProcess` and `AccessDenied`. Given the following code: ```python import psutil from psutil.tests import spawn_testproc sproc = spawn_testproc() p = psutil.Process(sproc.pid) p.terminate() p.wait() p.name() ``` Before we got: ``` Traceback (most recent call last): [...] File "/home/giampaolo/svn/psutil/psutil/_common.py", line 746, in open_binary return open(fname, "rb", buffering=FILE_READ_BUFFER_SIZE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: '/proc/105496/stat' During handling of the above exception, another exception occurred: Traceback (most recent call last): [...] File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1659, in wrapper raise NoSuchProcess(pid, name) psutil.NoSuchProcess: process no longer exists (pid=105496) ``` Now we get: ``` Traceback (most recent call last): [...] File "/home/giampaolo/svn/psutil/psutil/_common.py", line 746, in open_binary return open(fname, "rb", buffering=FILE_READ_BUFFER_SIZE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FileNotFoundError: [Errno 2] No such file or directory: '/proc/105496/stat' The above exception was the direct cause of the following exception: Traceback (most recent call last): [...] File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1659, in wrapper raise NoSuchProcess(pid, name) from None psutil.NoSuchProcess: process no longer exists (pid=105496) ``` Diff: ```diff FileNotFoundError: [Errno 2] No such file or directory: '/proc/105496/stat' - During handling of the above exception, another exception occurred: + The above exception was the direct cause of the following exception: Traceback (most recent call last): [...] File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 1659, in wrapper - raise NoSuchProcess(pid, name) + raise NoSuchProcess(pid, name) from None psutil.NoSuchProcess: process no longer exists (pid=105496) ```
About dropping Python 2.7 support, 3 years ago I stated:
3 years later (and to my surprise) downloads for Python 2.7 dropped to 0.36%. These are downloads per month:
According to pypistats.org it's 0.28% of the total, and around 15.000 downloads per day.
Maintaining 2.7 support has become increasingly difficult, but still possible. E.g. we can still run tests by using old PYPI backports. GitHub Actions can still be tweaked to run tests and produce wheels on Linux and macOS. Not Windows though, for which we have to use a separate service (Appveyor).
Still, the amount of hacks in psutil source code necessary to support Python 2.7 piled up over the years, and became quite big. Some disadvantages that come to mind:
#if PY_MAJOR_VERSION <= 3
, etc.)enum
s, which creates a difference on how CONSTANTS are exposed in terms of APItwine
, so that'll be a problem (CC @potiuk)As such I decided to finally drop support for Python 2.7. Current psutil 6.1.1 release will still support Python 2.7, but next 7.0.0 will not.
We can still make a promise that the 6.1.* line (EDIT: see python2 branch) will keep supporting Python 2.7 and will receive critical bug-fixes only (no new features).
In 7.0.0 we can keep the setup.py script compatible with Python 2.7 in terms of syntax, so that it can emit an informative error message on pip install. E.g. the user will see something like this:
Related tickets:
The text was updated successfully, but these errors were encountered: