blob: f088cfb0b12d66b5be03b0251c39922f7eaf92c6 [file] [edit]
Migration guide
===============
This page summarises the breaking changes introduced in each major release and
shows the code changes required to upgrade.
.. note::
Minor and patch releases (e.g. 6.1.x, 7.1.x) never contain breaking changes.
Only major releases are listed here.
.. _migration-8.0:
Migrating to 8.0
-----------------
Key breaking changes in 8.0:
- :func:`process_iter` pre-fetches values
- :attr:`Process.info` is deprecated: use direct methods.
- Named tuple field order changed: stop positional unpacking.
- Some return types are now enums instead of strings.
- :meth:`Process.memory_full_info` deprecated: use
:meth:`Process.memory_footprint`.
- New :meth:`Process.memory_info_ex` (unrelated to the old method deprecated in
4.0 and removed in 7.0).
- New :attr:`Process.attrs`: :class:`frozenset` of valid attribute names;
``process_iter(attrs=[])`` is deprecated.
- Python 3.6 dropped.
.. important::
Do not rely on positional unpacking of named tuples. Always use attribute
access (e.g. ``t.rss``).
process_iter(): p.info is deprecated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:func:`process_iter` now caches pre-fetched values internally, so they can be
accessed via normal method calls instead of the :attr:`Process.info` dict.
``p.info`` still works, but raises :exc:`DeprecationWarning`.
.. code-block:: python
import psutil
# before
for p in psutil.process_iter(attrs=["name", "status"]):
print(p.info["name"], p.info["status"])
# after
for p in psutil.process_iter(attrs=["name", "status"]):
print(p.name(), p.status()) # return cached values, never raise
When ``attrs`` are specified, method calls return cached values (no extra
syscall), and :exc:`AccessDenied` / :exc:`ZombieProcess` are handled
transparently (returning ``ad_value``).
If you relied on :attr:`Process.info` because you needed a dict structure, use
:meth:`Process.as_dict` instead.
.. code-block:: python
import psutil
# before
for p in psutil.process_iter(attrs=["name", "status"]):
print(p.info)
# after
attrs = ["name", "status"]
for p in psutil.process_iter(attrs=attrs):
print(p.as_dict(attrs)) # return cached values, never raise
.. note::
If ``"name"`` was pre-fetched via ``attrs``, calling ``p.name()`` no longer
raises :exc:`AccessDenied`. It returns ``ad_value`` instead. If you need the
exception, do not include the method in ``attrs``.
Named tuple field order changed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :func:`cpu_times`: :field:`user`, :field:`system`, :field:`idle` fields
changed order on Linux, macOS and BSD. They are now always the first 3 fields
on all platforms, with platform-specific fields (e.g. :field:`nice`)
following. Positional access (e.g. ``cpu_times()[3]``) will silently return
the wrong field. Always use attribute access instead (e.g.
``cpu_times().idle``).
.. code-block:: python
# before
user, nice, system, idle = psutil.cpu_times()
# after
t = psutil.cpu_times()
user, system, idle = t.user, t.system, t.idle
- :meth:`Process.memory_info`: the returned named tuple changed size and field
order. Always use attribute access (e.g. ``p.memory_info().rss``) instead of
positional unpacking.
- Linux: :field:`lib` and :field:`dirty` fields removed (aliases emitting
:exc:`DeprecationWarning` are kept).
- macOS: :field:`pfaults` and :field:`pageins` removed with **no aliases**.
Use :meth:`Process.page_faults` instead.
- Windows: old aliases (:field:`wset`, :field:`peak_wset`, :field:`pagefile`,
:field:`private`, :field:`peak_pagefile`, :field:`num_page_faults`) were
renamed. Old names still work but raise :exc:`DeprecationWarning`.
:field:`paged_pool`, :field:`nonpaged_pool`, :field:`peak_paged_pool`,
:field:`peak_nonpaged_pool` were moved to :meth:`Process.memory_info_ex`.
- BSD: a new :field:`peak_rss` field was added.
- :func:`virtual_memory`: on Windows, new :field:`cached` and :field:`wired`
fields were added. Code using positional unpacking will break:
.. code-block:: python
# before
total, avail, percent, used, free = psutil.virtual_memory()
# after
m = psutil.virtual_memory()
total, avail, percent, used, free = m.total, m.available, m.percent, m.used, m.free
cpu_times() interrupt renamed to irq on Windows
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :field:`interrupt` field of :func:`cpu_times` on Windows was renamed to
:field:`irq` to match the name used on Linux and BSD. The old name still works
but raises :exc:`DeprecationWarning`.
Status and connection fields are now enums
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :meth:`Process.status` now returns a :class:`ProcessStatus` member instead of
a plain ``str``.
- :meth:`Process.net_connections` and :func:`net_connections` :field:`status`
field now returns a :class:`ConnectionStatus` member instead of a plain
``str``.
Because both are :class:`enum.StrEnum` subclasses they compare equal to their
string values, so existing comparisons like
``p.status() == psutil.STATUS_RUNNING`` continue to work unchanged. Code
inspecting :func:`repr` or :class:`type` may need updating.
memory_full_info() is deprecated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:meth:`Process.memory_full_info` is deprecated. Use
:meth:`Process.memory_footprint` instead (same fields).
New memory_info_ex() method
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8.0 introduces a new :meth:`Process.memory_info_ex` method that extends
:meth:`Process.memory_info` with platform-specific metrics (e.g.
:field:`peak_rss`, :field:`swap`, :field:`rss_anon` on Linux). This is
**unrelated** to the old :meth:`Process.memory_info_ex` that was deprecated in
4.0 and removed in 7.0 (which corresponded to what later became
:meth:`Process.memory_full_info`).
New Process.attrs class attribute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:attr:`Process.attrs` is a new :class:`frozenset` exposing the valid attribute
names accepted by :meth:`Process.as_dict` and :func:`process_iter`. It replaces
the previous pattern of creating a throwaway process just to discover available
names:
.. code-block:: python
# before
attrs = list(psutil.Process().as_dict().keys())
# after
attrs = psutil.Process.attrs
It also makes it easy to pass all or a subset of attributes.
``process_iter(attrs=[])`` (empty list meaning "all") is now deprecated; use
:attr:`Process.attrs` instead:
.. code-block:: python
# all attrs
psutil.process_iter(attrs=psutil.Process.attrs)
# all except connections
psutil.process_iter(attrs=psutil.Process.attrs - {"net_connections"})
Python 3.6 dropped
^^^^^^^^^^^^^^^^^^^^
Python 3.6 is no longer supported. Minimum version is Python 3.7.
Git tags renamed
^^^^^^^^^^^^^^^^^
Git tags were renamed from ``release-X.Y.Z`` to ``vX.Y.Z`` (e.g.
``release-7.2.2`` ``v7.2.2``). Old tags are kept for backward compatibility.
If you reference psutil tags in scripts or URLs, update them to the new format.
See :gh:`2788`.
-------------------------------------------------------------------------------
.. _migration-7.0:
Migrating to 7.0
-----------------
Process.memory_info_ex() removed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The long-deprecated :meth:`Process.memory_info_ex` was removed (it was
deprecated since 4.0.0 in 2016). Use :meth:`Process.memory_full_info` instead.
.. note::
In 8.0, a new :meth:`Process.memory_info_ex` method was introduced with
different semantics: it extends :meth:`Process.memory_info` with
platform-specific metrics. It is unrelated to the old method documented here.
.. code-block:: python
# before
p.memory_info_ex()
# after
p.memory_full_info()
Python 2.7 dropped
^^^^^^^^^^^^^^^^^^^^
Python 2.7 is no longer supported. The last release to support Python 2.7 is
psutil 6.1.x:
.. code-block:: bash
pip2 install "psutil==6.1.*"
-------------------------------------------------------------------------------
.. _migration-6.0:
Migrating to 6.0
-----------------
Process.connections() renamed
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:meth:`Process.connections` was renamed to :meth:`Process.net_connections` for
consistency with the system-level :func:`net_connections`. The old name
triggers a :exc:`DeprecationWarning` and will be removed in a future release:
.. code-block:: python
# before
p.connections()
p.connections(kind="tcp")
# after
p.net_connections()
p.net_connections(kind="tcp")
disk_partitions() lost two fields
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :field:`maxfile` and :field:`maxpath` fields were removed from the named
tuple returned by :func:`disk_partitions`. Code unpacking the tuple
positionally will break:
.. code-block:: python
# before (broken)
device, mountpoint, fstype, opts, maxfile, maxpath = part
# after
device, mountpoint, fstype, opts = (
part.device, part.mountpoint, part.fstype, part.opts
)
process_iter() no longer checks for PID reuse
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:func:`process_iter` no longer preemptively checks whether yielded PIDs have
been reused (this made it ~20× faster). If you need to verify that a process
object is still alive and refers to the same process, use
:meth:`Process.is_running` explicitly:
.. code-block:: python
for p in psutil.process_iter(["name"]):
if p.is_running():
print(p.pid, p.name())
-------------------------------------------------------------------------------
.. _migration-5.0:
Migrating to 5.0
-----------------
5.0.0 was the largest renaming in psutil history. All ``get_*`` and ``set_*``
:class:`Process` methods lost their prefix, and several module-level names were
changed.
Old :class:`Process` method names still worked but raised
:exc:`DeprecationWarning`. They were fully removed in 6.0.
Process methods
^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: 40 40
* - Old (< 5.0)
- New (>= 5.0)
* - ``p.get_children()``
- ``p.children()``
* - ``p.get_connections()``
- ``p.connections()`` ``p.net_connections()`` in 6.0
* - ``p.get_cpu_affinity()``
- ``p.cpu_affinity()``
* - ``p.get_cpu_percent()``
- ``p.cpu_percent()``
* - ``p.get_cpu_times()``
- ``p.cpu_times()``
* - ``p.get_ext_memory_info()``
- ``p.memory_info_ex()`` ``p.memory_full_info()`` in 4.0
* - ``p.get_io_counters()``
- ``p.io_counters()``
* - ``p.get_ionice()``
- ``p.ionice()``
* - ``p.get_memory_info()``
- ``p.memory_info()``
* - ``p.get_memory_maps()``
- ``p.memory_maps()``
* - ``p.get_memory_percent()``
- ``p.memory_percent()``
* - ``p.get_nice()``
- ``p.nice()``
* - ``p.get_num_ctx_switches()``
- ``p.num_ctx_switches()``
* - ``p.get_num_fds()``
- ``p.num_fds()``
* - ``p.get_num_threads()``
- ``p.num_threads()``
* - ``p.get_open_files()``
- ``p.open_files()``
* - ``p.get_rlimit()``
- ``p.rlimit()``
* - ``p.get_threads()``
- ``p.threads()``
* - ``p.getcwd()``
- ``p.cwd()``
* - ``p.set_nice(v)``
- ``p.nice(v)``
* - ``p.set_ionice(cls)``
- ``p.ionice(cls)``
* - ``p.set_cpu_affinity(cpus)``
- ``p.cpu_affinity(cpus)``
Module-level renames
^^^^^^^^^^^^^^^^^^^^^
.. list-table::
:header-rows: 1
:widths: 40 40
* - Old (< 5.0)
- New (>= 5.0)
* - ``psutil.NUM_CPUS``
- ``psutil.cpu_count()``
* - ``psutil.BOOT_TIME``
- ``psutil.boot_time()``
* - ``psutil.TOTAL_PHYMEM``
- ``psutil.virtual_memory().total``
* - ``psutil.get_pid_list()``
- ``psutil.pids()``
* - ``psutil.get_users()``
- ``psutil.users()``
* - ``psutil.get_boot_time()``
- ``psutil.boot_time()``
* - ``psutil.network_io_counters()``
- ``psutil.net_io_counters()``
* - ``psutil.phymem_usage()``
- ``psutil.virtual_memory()``
* - ``psutil.virtmem_usage()``
- ``psutil.swap_memory()``