Bug 1620513 - Upgrade psutil to 5.7.0. r=rstewart

Differential Revision: https://phabricator.services.mozilla.com/D65685

--HG--
rename : third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/METADATA => third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/METADATA
rename : third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/WHEEL => third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/WHEEL
rename : third_party/python/psutil-cp27-none-win_amd64/psutil-5.4.3.dist-info/top_level.txt => third_party/python/psutil-cp27-none-win_amd64/psutil-5.7.0.dist-info/top_level.txt
rename : third_party/python/psutil/psutil/tests/runner.py => third_party/python/psutil-cp27-none-win_amd64/psutil/tests/runner.py
rename : third_party/python/psutil/psutil/arch/windows/wmi.h => third_party/python/psutil/psutil/arch/windows/net.h
rename : third_party/python/psutil/psutil/arch/windows/wmi.h => third_party/python/psutil/psutil/arch/windows/socks.h
rename : third_party/python/psutil/scripts/internal/download_exes.py => third_party/python/psutil/scripts/internal/win_download_wheels.py
extra : moz-landing-system : lando
This commit is contained in:
Mike Hommey 2020-03-06 21:03:01 +00:00
Родитель cae18cfff0
Коммит f46e46f7fa
169 изменённых файлов: 11451 добавлений и 9957 удалений

Просмотреть файл

@ -1,472 +0,0 @@
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://readthedocs.org/projects/psutil/badge/?version=latest
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
:target: https://pypi.python.org/pypi/psutil/
:alt: Latest version
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
:target: https://github.com/giampaolo/psutil/
:alt: Github stars
.. image:: https://img.shields.io/pypi/l/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
:alt: License
===========
Quick links
===========
- `Home page <https://github.com/giampaolo/psutil>`_
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `Documentation <http://psutil.readthedocs.io>`_
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
- `Forum <http://groups.google.com/group/psutil/topics>`_
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
=======
Summary
=======
psutil (process and system utilities) is a cross-platform library for
retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network, sensors) in Python.
It is useful mainly for **system monitoring**, **profiling and limiting process
resources** and **management of running processes**.
It implements many functionalities offered by UNIX command line tools such as:
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
iotop, uptime, pidof, tty, taskset, pmap.
psutil currently supports the following platforms:
- **Linux**
- **Windows**
- **OSX**,
- **FreeBSD, OpenBSD**, **NetBSD**
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures, with Python
versions from **2.6 to 3.6**.
`PyPy <http://pypy.org/>`__ is also known to work.
====================
Example applications
====================
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png |
| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png |
+------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
=====================
Projects using psutil
=====================
At the time of writing psutil has roughly
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
per month and there are over
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
on github which depend from psutil.
Here's some I find particularly interesting:
- https://github.com/facebook/osquery/
- https://github.com/nicolargo/glances
- https://github.com/google/grr
- https://github.com/Jahaja/psdash
- https://github.com/ajenti/ajenti
- https://github.com/home-assistant/home-assistant/
========
Portings
========
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
==============
Example usages
==============
CPU
===
.. code-block:: python
>>> import psutil
>>> psutil.cpu_times()
scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
>>>
>>> for x in range(3):
... psutil.cpu_percent(interval=1)
...
4.0
5.9
3.8
>>>
>>> for x in range(3):
... psutil.cpu_percent(interval=1, percpu=True)
...
[4.0, 6.9, 3.7, 9.2]
[7.0, 8.5, 2.4, 2.1]
[1.2, 9.0, 9.9, 7.2]
>>>
>>> for x in range(3):
... psutil.cpu_times_percent(interval=1, percpu=False)
...
scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)
>>>
>>> psutil.cpu_count()
4
>>> psutil.cpu_count(logical=False)
2
>>>
>>> psutil.cpu_stats()
scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0)
>>>
>>> psutil.cpu_freq()
scpufreq(current=931.42925, min=800.0, max=3500.0)
>>>
Memory
======
.. code-block:: python
>>> import psutil
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
>>> psutil.swap_memory()
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
>>>
Disks
=====
.. code-block:: python
>>> import psutil
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
>>>
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
>>>
>>> psutil.disk_io_counters(perdisk=False)
sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412)
>>>
Network
=======
.. code-block:: python
>>> import psutil
>>> psutil.net_io_counters(pernic=True)
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
>>>
>>> psutil.net_connections()
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT', pid=None)
...]
>>>
>>> psutil.net_if_addrs()
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>
>>> psutil.net_if_stats()
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
>>>
Sensors
=======
.. code-block:: python
>>> import psutil
>>> psutil.sensors_temperatures()
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
>>>
>>> psutil.sensors_fans()
{'asus': [sfan(label='cpu_fan', current=3200)]}
>>>
>>> psutil.sensors_battery()
sbattery(percent=93, secsleft=16628, power_plugged=False)
>>>
Other system info
=================
.. code-block:: python
>>> import psutil
>>> psutil.users()
[suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352),
suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)]
>>>
>>> psutil.boot_time()
1365519115.0
>>>
Process management
==================
.. code-block:: python
>>> import psutil
>>> psutil.pids()
[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244,
1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282,
4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446,
5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
>>>
>>> p = psutil.Process(7055)
>>> p.name()
'python'
>>> p.exe()
'/usr/bin/python'
>>> p.cwd()
'/home/giampaolo'
>>> p.cmdline()
['/usr/bin/python', 'main.py']
>>>
>>> p.pid
7055
>>> p.ppid()
7054
>>> p.parent()
<psutil.Process(pid=7054, name='bash') at 140008329539408>
>>> p.children()
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
<psutil.Process(pid=8044, name='python') at 19229444921932>]
>>>
>>> p.status()
'running'
>>> p.username()
'giampaolo'
>>> p.create_time()
1267551141.5019531
>>> p.terminal()
'/dev/pts/0'
>>>
>>> p.uids()
puids(real=1000, effective=1000, saved=1000)
>>> p.gids()
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
[0, 1, 2, 3]
>>> p.cpu_affinity([0, 1]) # set
>>> p.cpu_num()
1
>>>
>>> p.memory_info()
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
>>> p.memory_percent()
0.7823
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
...]
>>>
>>> p.io_counters()
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
>>>
>>> p.connections()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT')]
>>>
>>> p.num_threads()
4
>>> p.num_fds()
8
>>> p.threads()
[pthread(id=5234, user_time=22.5, system_time=9.2891),
pthread(id=5235, user_time=0.0, system_time=0.0),
pthread(id=5236, user_time=0.0, system_time=0.0),
pthread(id=5237, user_time=0.0707, system_time=1.1)]
>>>
>>> p.num_ctx_switches()
pctxsw(voluntary=78, involuntary=19)
>>>
>>> p.nice()
0
>>> p.nice(10) # set
>>>
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
>>> p.ionice()
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
>>>
>>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only)
>>> p.rlimit(psutil.RLIMIT_NOFILE)
(5, 5)
>>>
>>> p.environ()
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
...}
>>>
>>> p.as_dict()
{'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...}
>>> p.is_running()
True
>>> p.suspend()
>>> p.resume()
>>>
>>> p.terminate()
>>> p.wait(timeout=3)
0
>>>
>>> psutil.test()
USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
root 1 0.0 0.0 24584 2240 Jun17 00:00 init
root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
...
giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1
>>>
Further process APIs
====================
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
... print(proc.info)
...
{'pid': 1, 'name': 'systemd'}
{'pid': 2, 'name': 'kthreadd'}
{'pid': 3, 'name': 'ksoftirqd/0'}
...
>>>
>>> psutil.pid_exists(3)
True
>>>
>>> def on_terminate(proc):
... print("process {} terminated".format(proc))
...
>>> # waits for multiple processes to terminate
>>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate)
>>>
Popen wrapper:
.. code-block:: python
>>> import psutil
>>> from subprocess import PIPE
>>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE)
>>> p.name()
'python'
>>> p.username()
'giampaolo'
>>> p.communicate()
('hello\n', None)
>>> p.wait(timeout=2)
0
>>>
Windows services
================
.. code-block:: python
>>> list(psutil.win_service_iter())
[<WindowsService(name='AeLookupSvc', display_name='Application Experience') at 38850096>,
<WindowsService(name='ALG', display_name='Application Layer Gateway Service') at 38850128>,
<WindowsService(name='APNMCP', display_name='Ask Update Service') at 38850160>,
<WindowsService(name='AppIDSvc', display_name='Application Identity') at 38850192>,
...]
>>> s = psutil.win_service_get('alg')
>>> s.as_dict()
{'binpath': 'C:\\Windows\\System32\\alg.exe',
'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing',
'display_name': 'Application Layer Gateway Service',
'name': 'alg',
'pid': None,
'start_type': 'manual',
'status': 'stopped',
'username': 'NT AUTHORITY\\LocalService'}
Other samples
=============
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
======
Author
======
psutil was created and is maintained by
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
A lot of time and effort went into making psutil as it is right now.
If you feel psutil is useful to you or your business and want to support its
future development please consider donating me
(`Giampaolo <http://grodola.blogspot.com/p/about.html>`__) some money.
.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
:alt: Donate via PayPal
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <https://www.linkedin.com/in/grodola>`_.

Просмотреть файл

@ -1,34 +0,0 @@
psutil/__init__.py,sha256=220_B4k7vC9eoVP_OW8SFcaXCSBGpj_nacxvfBQ5O2o,84989
psutil/_common.py,sha256=df5J2HqrWvGoFdumxDL1q9fgJOOYyiCmV0EFxb4ghuY,17852
psutil/_compat.py,sha256=0VqlfcCGD5tZRBW-mFroguS0J7YNw6y3LjEcX5ChXDc,8170
psutil/_exceptions.py,sha256=37eRgLuwTy7X4tjovePfZfYif-veW6LFeRlPqsgnNBU,3009
psutil/_psaix.py,sha256=uAqwhQHS0upGc8OIk8Qa5PScCwXNvaMkoIdltZZ0n8A,19376
psutil/_psbsd.py,sha256=ewmj2_DfzZpQZEcRvo1xvjVFhQqJidnENLgS8jrBb68,30244
psutil/_pslinux.py,sha256=ME3wEgxfOWSFxgKXpTKbFw29ur1toMT4DdkKLJGkaD4,74850
psutil/_psosx.py,sha256=X2WzhpuGjffjzFt3B3hphX7piPRCrPsjJrk6p6vu96w,17213
psutil/_psposix.py,sha256=AmpZmKnvzCFcf7RpYypiUxOxKoRdXHRy2p9hFEIAJVc,6345
psutil/_pssunos.py,sha256=uEsntvZPXplCuP9ER2W1QaGXjOqUZx_qFx2iLeyc5V8,25650
psutil/_psutil_windows.pyd,sha256=wbQ_dSXTvdmCyQV02P7uCk95MwDkZ_D1g5r4G7IiYr8,59904
psutil/_pswindows.py,sha256=_KYB-Vyhnz2A3l8I7tuXvFSrBPqKIb9slcwh5Azj0QU,33121
psutil/tests/__init__.py,sha256=hkGHtLQNHjKrqhuV3Sk0kkHir17Mlam-amZBkLdfGwA,37656
psutil/tests/__main__.py,sha256=dssAzXI-sAHkObtruDvc1cYUFNWOi-ZXETQgwaLKJS0,2784
psutil/tests/test_aix.py,sha256=_ItFqb-CmYHlnlcduSKbgsPBw_xEIfE5v_pOr_YD8gw,4483
psutil/tests/test_bsd.py,sha256=aif308A3TRnPZGY1tmNlH25YCweeSMpwbkah2K13wZs,17785
psutil/tests/test_connections.py,sha256=eXOPOkusHO6Xc8gNrDxPBhq1Ni2fYYe0AAzeGU4gijQ,20676
psutil/tests/test_contracts.py,sha256=ryPd7QDkQKxh8Mjcl-iPflXw5OTi8TWWLzQjIJ4EW2w,24136
psutil/tests/test_linux.py,sha256=_gQBxUSiRSygoGfFXn-2m5XpXJQMQSiurVobrwkaAgc,78746
psutil/tests/test_memory_leaks.py,sha256=v-RmU0BAzH05pkQ1dUV1hUXxlMva7943GFvT9Erl6J4,18259
psutil/tests/test_misc.py,sha256=4qu61Sdmvzbaz2heOXKlg_PveYrzamBIUJ5QlLIYmSQ,37821
psutil/tests/test_osx.py,sha256=UL3sovPp-5f0LIjNqjHu12NnpXF2uuv8Z62wbeAJj2c,9652
psutil/tests/test_posix.py,sha256=4gm2VeCYoPYnstn_2GMG18c6xvMV7APXA26W5Dcm99s,16397
psutil/tests/test_process.py,sha256=IE-v3DHKIje6Kwnas8kzfsbz15L4-0dpI555lXg7-NE,60495
psutil/tests/test_sunos.py,sha256=UNywEx_qlSOyUHV48lMKqmnu8RKPBDCQrO0llulCUHY,1322
psutil/tests/test_system.py,sha256=fv3otFKJVOn3VpRrD5IMivbI-hfajL6wmzVQF_JJqDI,34885
psutil/tests/test_unicode.py,sha256=M0VTr_kGgmDKiNq6nSvraaw-711pRXe_6R948qHAr8I,12913
psutil/tests/test_windows.py,sha256=AG2Feks59VOahEW_hJs_o4f5wt20vS1jxxaUCijcwAQ,32609
psutil-5.4.3.dist-info/DESCRIPTION.rst,sha256=oATWrkVX56oC_b77TIXQsrm1CxSgD93PM71km6ud5G4,19853
psutil-5.4.3.dist-info/METADATA,sha256=neLhT7NMfWptGzaSxueDDYqVDOR0C9cNvE8pAK14C2c,22835
psutil-5.4.3.dist-info/RECORD,,
psutil-5.4.3.dist-info/WHEEL,sha256=oT-jJdPOIfRdvpqTJO9X6OjCsyUImH2THoT54KREdwI,106
psutil-5.4.3.dist-info/metadata.json,sha256=RqO1wxtF8F5B2HqYztzUkdKh5XmF8Wq_PxB9l571GM0,2492
psutil-5.4.3.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7

Просмотреть файл

@ -1 +0,0 @@
{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Environment :: Win32 (MS Windows)", "Intended Audience :: Developers", "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "License :: OSI Approved :: BSD License", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows :: Windows NT/2000", "Operating System :: Microsoft", "Operating System :: OS Independent", "Operating System :: POSIX :: BSD :: FreeBSD", "Operating System :: POSIX :: BSD :: NetBSD", "Operating System :: POSIX :: BSD :: OpenBSD", "Operating System :: POSIX :: BSD", "Operating System :: POSIX :: Linux", "Operating System :: POSIX :: SunOS/Solaris", "Operating System :: POSIX", "Programming Language :: C", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries", "Topic :: System :: Benchmark", "Topic :: System :: Hardware", "Topic :: System :: Monitoring", "Topic :: System :: Networking :: Monitoring", "Topic :: System :: Networking", "Topic :: System :: Operating System", "Topic :: System :: Systems Administration", "Topic :: Utilities"], "extensions": {"python.details": {"contacts": [{"email": "g.rodola@gmail.com", "name": "Giampaolo Rodola", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/giampaolo/psutil"}}}, "extras": ["enum"], "generator": "bdist_wheel (0.30.0)", "keywords": ["ps", "top", "kill", "free", "lsof", "netstat", "nice", "tty", "ionice", "uptime", "taskmgr", "process", "df", "iotop", "iostat", "ifconfig", "taskset", "who", "pidof", "pmap", "smem", "pstree", "monitoring", "ulimit", "prlimit", "smem"], "license": "BSD", "metadata_version": "2.0", "name": "psutil", "platform": "Platform Independent", "run_requires": [{"extra": "enum", "requires": ["enum34"]}], "summary": "Cross-platform lib for process and system monitoring in Python.", "test_requires": [{"requires": ["ipaddress", "mock"]}], "version": "5.4.3"}

Просмотреть файл

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola'
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the psutil authors nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@ -1,12 +1,12 @@
Metadata-Version: 2.0
Metadata-Version: 2.1
Name: psutil
Version: 5.4.3
Version: 5.7.0
Summary: Cross-platform lib for process and system monitoring in Python.
Home-page: https://github.com/giampaolo/psutil
Author: Giampaolo Rodola
Author-email: g.rodola@gmail.com
License: BSD
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability
Platform: Platform Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
@ -16,9 +16,16 @@ Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: Microsoft :: Windows :: Windows 7
Classifier: Operating System :: Microsoft :: Windows :: Windows 8
Classifier: Operating System :: Microsoft :: Windows :: Windows 8.1
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2003
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2008
Classifier: Operating System :: Microsoft :: Windows :: Windows Vista
Classifier: Operating System :: Microsoft
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: AIX
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
Classifier: Operating System :: POSIX :: BSD :: NetBSD
Classifier: Operating System :: POSIX :: BSD :: OpenBSD
@ -31,67 +38,108 @@ Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Benchmark
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: Topic :: System :: Hardware
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring :: Hardware Watchdog
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Operating System
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
Provides-Extra: enum
Requires-Dist: enum34; extra == 'enum'
Requires-Dist: enum34 ; extra == 'enum'
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20OSX
| |downloads| |stars| |forks| |contributors| |coverage| |quality|
| |version| |py-versions| |packages| |license|
| |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift|
.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pepy.tech/project/psutil
:alt: Downloads
.. |stars| image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
:target: https://github.com/giampaolo/psutil/stargazers
:alt: Github stars
.. |forks| image:: https://img.shields.io/github/forks/giampaolo/psutil.svg
:target: https://github.com/giampaolo/psutil/network/members
:alt: Github forks
.. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/psutil.svg
:target: https://github.com/giampaolo/psutil/graphs/contributors
:alt: Contributors
.. |quality| image:: https://img.shields.io/codacy/grade/ce63e7f7f69d44b5b59682196e6fbfca.svg
:target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=giampaolo/psutil&amp;utm_campaign=Badge_Grade
:alt: Code quality
.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master
.. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD
:target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci
:alt: FreeBSD tests (Cirrus-Ci)
.. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://readthedocs.org/projects/psutil/badge/?version=latest
.. |doc| image:: https://readthedocs.org/projects/psutil/badge/?version=latest
:target: http://psutil.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
:target: https://pypi.python.org/pypi/psutil/
.. |version| image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi
:target: https://pypi.org/project/psutil
:alt: Latest version
.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg
:target: https://github.com/giampaolo/psutil/
:alt: Github stars
.. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg
:target: https://pypi.org/project/psutil
:alt: Supported Python versions
.. image:: https://img.shields.io/pypi/l/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
.. |packages| image:: https://repology.org/badge/tiny-repos/python:psutil.svg
:target: https://repology.org/metapackage/python:psutil/versions
:alt: Binary packages
.. |license| image:: https://img.shields.io/pypi/l/psutil.svg
:target: https://github.com/giampaolo/psutil/blob/master/LICENSE
:alt: License
===========
.. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow&style=flat&logo=twitter&logoColor=4FADFF
:target: https://twitter.com/grodola
:alt: Twitter Follow
.. |tidelift| image:: https://tidelift.com/badges/github/giampaolo/psutil?style=flat
:target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
:alt: Tidelift
-----
Quick links
===========
- `Home page <https://github.com/giampaolo/psutil>`_
- `Install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `Documentation <http://psutil.readthedocs.io>`_
- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_
- `Download <https://pypi.org/project/psutil/#files>`_
- `Forum <http://groups.google.com/group/psutil/topics>`_
- `StackOverflow <https://stackoverflow.com/questions/tagged/psutil>`_
- `Blog <http://grodola.blogspot.com/search/label/psutil>`_
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
- `Development guide <https://github.com/giampaolo/psutil/blob/master/docs/DEVGUIDE.rst>`_
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
=======
Summary
=======
@ -100,23 +148,48 @@ retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network, sensors) in Python.
It is useful mainly for **system monitoring**, **profiling and limiting process
resources** and **management of running processes**.
It implements many functionalities offered by UNIX command line tools such as:
ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat,
iotop, uptime, pidof, tty, taskset, pmap.
It implements many functionalities offered by classic UNIX command line tools
such as *ps, top, iotop, lsof, netstat, ifconfig, free* and others.
psutil currently supports the following platforms:
- **Linux**
- **Windows**
- **OSX**,
- **macOS**
- **FreeBSD, OpenBSD**, **NetBSD**
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures, with Python
versions from **2.6 to 3.6**.
`PyPy <http://pypy.org/>`__ is also known to work.
...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 <http://pypy.org/>`__ is also known to work.
psutil for enterprise
=====================
.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
:width: 150
:alt: Tidelift
:target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
.. list-table::
:widths: 10 150
* - |tideliftlogo|
- The maintainer of psutil and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the open
source dependencies you use to build your applications. Save time,
reduce risk, and improve code health, while paying the maintainers of
the exact dependencies you use.
`Learn more <https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`__.
By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support
psutil future development. Alternatively consider making a small
`donation`_.
Security
========
To report a security vulnerability, please use the `Tidelift security
contact`_. Tidelift will coordinate the fix and disclosure.
====================
Example applications
====================
@ -131,45 +204,49 @@ Example applications
Also see `scripts directory <https://github.com/giampaolo/psutil/tree/master/scripts>`__
and `doc recipes <http://psutil.readthedocs.io/#recipes/>`__.
=====================
Projects using psutil
=====================
At the time of writing psutil has roughly
`2.9 milion downloads <https://github.com/giampaolo/psutil/issues/1053#issuecomment-340166262>`__
per month and there are over
`6000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
psutil has roughly the following monthly downloads:
.. image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pepy.tech/project/psutil
:alt: Downloads
There are over
`10.000 open source projects <https://libraries.io/pypi/psutil/dependent_repositories?page=1>`__
on github which depend from psutil.
Here's some I find particularly interesting:
- https://github.com/google/grr
- https://github.com/facebook/osquery/
- https://github.com/nicolargo/glances
- https://github.com/google/grr
- https://github.com/Jahaja/psdash
- https://github.com/ajenti/ajenti
- https://github.com/home-assistant/home-assistant/
========
Portings
========
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
==============
Example usages
==============
This represents pretty much the whole psutil API.
CPU
===
---
.. code-block:: python
>>> import psutil
>>>
>>> psutil.cpu_times()
scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0)
>>>
@ -205,13 +282,14 @@ CPU
>>> psutil.cpu_freq()
scpufreq(current=931.42925, min=800.0, max=3500.0)
>>>
>>> psutil.getloadavg() # also on Windows (emulated)
(3.14, 3.89, 4.67)
Memory
======
------
.. code-block:: python
>>> import psutil
>>> psutil.virtual_memory()
svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304)
>>> psutil.swap_memory()
@ -219,11 +297,10 @@ Memory
>>>
Disks
=====
-----
.. code-block:: python
>>> import psutil
>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
@ -236,11 +313,10 @@ Disks
>>>
Network
=======
-------
.. code-block:: python
>>> import psutil
>>> psutil.net_io_counters(pernic=True)
{'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0),
'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)}
@ -248,25 +324,23 @@ Network
>>> psutil.net_connections()
[sconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254),
sconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED', pid=None),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT', pid=None)
...]
>>>
>>> psutil.net_if_addrs()
{'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
{'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)],
'wlan0': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None),
snicaddr(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
>>>
>>> psutil.net_if_stats()
{'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}
{'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536),
'wlan0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500)}
>>>
Sensors
=======
-------
.. code-block:: python
@ -275,10 +349,7 @@ Sensors
{'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)],
'asus': [shwtemp(label='', current=47.0, high=None, critical=None)],
'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 1', current=52.0, high=100.0, critical=100.0),
shwtemp(label='Core 2', current=45.0, high=100.0, critical=100.0),
shwtemp(label='Core 3', current=47.0, high=100.0, critical=100.0)]}
shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]}
>>>
>>> psutil.sensors_fans()
{'asus': [sfan(label='cpu_fan', current=3200)]}
@ -288,7 +359,7 @@ Sensors
>>>
Other system info
=================
-----------------
.. code-block:: python
@ -302,7 +373,7 @@ Other system info
>>>
Process management
==================
------------------
.. code-block:: python
@ -314,6 +385,8 @@ Process management
5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]
>>>
>>> p = psutil.Process(7055)
>>> p
psutil.Process(pid=7055, name='python', started='09:04:44')
>>> p.name()
'python'
>>> p.exe()
@ -327,11 +400,16 @@ Process management
7055
>>> p.ppid()
7054
>>> p.children(recursive=True)
[psutil.Process(pid=29835, name='python2.7', started='11:45:38'),
psutil.Process(pid=29836, name='python2.7', started='11:43:39')]
>>>
>>> p.parent()
<psutil.Process(pid=7054, name='bash') at 140008329539408>
>>> p.children()
[<psutil.Process(pid=8031, name='python') at 14020832451977>,
<psutil.Process(pid=8044, name='python') at 19229444921932>]
psutil.Process(pid=4699, name='bash', started='09:06:44')
>>> p.parents()
[psutil.Process(pid=4699, name='bash', started='09:06:44'),
psutil.Process(pid=4689, name='gnome-terminal-server', started='0:06:44'),
psutil.Process(pid=1, name='systemd', started='05:56:55')]
>>>
>>> p.status()
'running'
@ -348,7 +426,7 @@ Process management
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
@ -359,14 +437,13 @@ Process management
>>>
>>> p.memory_info()
pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0)
>>> p.memory_full_info() # "real" USS memory usage (Linux, OSX, Win only)
>>> p.memory_full_info() # "real" USS memory usage (Linux, macOS, Win only)
pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0)
>>> p.memory_percent()
0.7823
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0),
pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, rss=32768, size=2134016, pss=15360, shared_clean=24576, shared_dirty=0, private_clean=0, private_dirty=8192, referenced=24576, anonymous=8192, swap=0),
pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0),
pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0),
...]
@ -375,14 +452,12 @@ Process management
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
[popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)]
>>>
>>> p.connections()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=60759), raddr=addr(ip='72.14.234.104', port=80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=51314), raddr=addr(ip='72.14.234.83', port=443), status='SYN_SENT')]
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')]
>>>
>>> p.num_threads()
4
@ -390,8 +465,6 @@ Process management
8
>>> p.threads()
[pthread(id=5234, user_time=22.5, system_time=9.2891),
pthread(id=5235, user_time=0.0, system_time=0.0),
pthread(id=5236, user_time=0.0, system_time=0.0),
pthread(id=5237, user_time=0.0707, system_time=1.1)]
>>>
>>> p.num_ctx_switches()
@ -411,7 +484,7 @@ Process management
>>>
>>> p.environ()
{'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto',
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'COLORTERM': 'gnome-terminal',
'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg',
...}
>>>
>>> p.as_dict()
@ -422,6 +495,7 @@ Process management
>>> p.resume()
>>>
>>> p.terminate()
>>> p.kill()
>>> p.wait(timeout=3)
0
>>>
@ -429,7 +503,6 @@ Process management
USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND
root 1 0.0 0.0 24584 2240 Jun17 00:00 init
root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd
root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0
...
giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4
giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome
@ -437,12 +510,12 @@ Process management
>>>
Further process APIs
====================
--------------------
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
>>> for proc in psutil.process_iter(['pid', 'name']):
... print(proc.info)
...
{'pid': 1, 'name': 'systemd'}
@ -478,7 +551,7 @@ Popen wrapper:
>>>
Windows services
================
----------------
.. code-block:: python
@ -499,26 +572,11 @@ Windows services
'status': 'stopped',
'username': 'NT AUTHORITY\\LocalService'}
Other samples
=============
See `doc recipes <http://psutil.readthedocs.io/#recipes>`__.
======
Author
======
psutil was created and is maintained by
`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`__.
A lot of time and effort went into making psutil as it is right now.
If you feel psutil is useful to you or your business and want to support its
future development please consider donating me
(`Giampaolo <http://grodola.blogspot.com/p/about.html>`__) some money.
.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif
:target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
:alt: Donate via PayPal
Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <https://www.linkedin.com/in/grodola>`_.
.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html
.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
.. _Tidelift security contact: https://tidelift.com/security
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme

Просмотреть файл

@ -0,0 +1,33 @@
psutil/__init__.py,sha256=gkuk8_HMEBXTFl0y4l8A5QGNCjUH1T0tpF_Y8hPJCPA,87126
psutil/_common.py,sha256=6kuDg4DKKv3OGndSXLQ3LftF_hPySIEOprC8HE49eag,26001
psutil/_compat.py,sha256=lrMSZr32TO6y9FQw7C2xTNyKwAnPU2o11xQrA_fS_Qw,11607
psutil/_psaix.py,sha256=u9M_jJqkiGqNgdhum9MZTbnS4pjIfdCHNr3HAYHA0GQ,18458
psutil/_psbsd.py,sha256=LHfBJ-iKy4fuumIcSjO7b6VFOvU_d-Pzwp7Eg84rHSw,30534
psutil/_pslinux.py,sha256=WtQtqOAhXd-zqtVPV-E0re91Vqj4DYrKQ3Mj9CfBWak,79806
psutil/_psosx.py,sha256=kvG3GKxA-L581H_UgU_BYaZ3eMPX7qMtEBM7AGC-t10,17090
psutil/_psposix.py,sha256=FtbNSosrJiiUb9l0gfFdTwNxUwQb6Icy4L3si0x6ZMA,6047
psutil/_pssunos.py,sha256=c-0et4xslK83ZiTizQ9W3LH0pMZy11ATEIBbQBJ_v-g,25398
psutil/_psutil_windows.pyd,sha256=jERIIv4AR_vfAvx8oOqkyv41JBPuMskRgnM1O8KdokE,62976
psutil/_pswindows.py,sha256=iFcfbA5KZehjdZfe1b-cLGRdavGNryI4Zxpkqb12UjU,36839
psutil/tests/__init__.py,sha256=uH3lPOnYc6179FxdSy4xfMeJOBvB9CZid268Pg_owC0,35141
psutil/tests/__main__.py,sha256=bBfMPu_gPzyiA4gfAFSZLk7LyLSPTUIHQFU1kFcj_Ok,291
psutil/tests/runner.py,sha256=l7BrTzIOdjPgNB3D3kiir8jBiK_QJKMlJSYu4Zr0_po,5188
psutil/tests/test_aix.py,sha256=LA8PR-1vx5DN2OkjU57MsO8uzNOB0y1ScR1yx5bZJyc,4464
psutil/tests/test_bsd.py,sha256=3zlUvefRm2fFTbyLrqM9u8NMK8CThLT7irioTGgnNts,20612
psutil/tests/test_connections.py,sha256=U2KCl7eW6kRds8S7t8SmZ62OrVSPfdBuksHsDlk2C28,25293
psutil/tests/test_contracts.py,sha256=BOKrRiZs625Xj3KZBzOZ8Kr6edAQgzHq0OlznoCxKzw,25355
psutil/tests/test_linux.py,sha256=KvqJ-LiINvbQQ3y18uM2SZRKnpnH4PqlA7CqWLRIH5s,87573
psutil/tests/test_memory_leaks.py,sha256=M5nWBv_PYfN7bIoaz6r0UqEYY79hO6wvvDfkKWFMETI,18499
psutil/tests/test_misc.py,sha256=wqXpnXL2ycHyE1vu3GB43XTET5auTKz9VdBSjr-vdp0,38748
psutil/tests/test_osx.py,sha256=oQIO0YReUtH0PFFAwyk8FpUqvjIiuhVPehMFS1AWJpM,9257
psutil/tests/test_posix.py,sha256=fSi5J1LxPhA7ZocrnLnqCSBn6JUuOtBeAljBWughIf4,16537
psutil/tests/test_process.py,sha256=JJB9VdAwKFYK-rlpvWn1NyeYasmr0nL_XetzFHHjaJU,63924
psutil/tests/test_sunos.py,sha256=GwqWfAP46nrxWlJr-srg85cPNEU2DXvoMelAgqegfLA,1294
psutil/tests/test_system.py,sha256=4nWe_fFRmnaB8epV7Eji_0JFnIJbvbykMgSi8LFzbKM,36162
psutil/tests/test_unicode.py,sha256=5v1hFoOQoi9_2Wg4ZTIWY_YDd29G00-59ln9FOe8Tsg,13246
psutil/tests/test_windows.py,sha256=cGjEspgL48Sb5BQeSG5kIU0DSeImPU1bL9cpFfNX2Tk,33666
psutil-5.7.0.dist-info/LICENSE,sha256=JMEphFAMqgf_3OGe68BjlsXm0kS1c7xsQ49KbvjlbBs,1549
psutil-5.7.0.dist-info/METADATA,sha256=RmX2_-V4HrxQ1p78U2Os4H5Q0ZFvF5oc0uUTUt9-sRo,25022
psutil-5.7.0.dist-info/WHEEL,sha256=Yt_rpa18HI_NXs5dEYG1uWuZ-4QRLVJrN8TSetG3BOI,106
psutil-5.7.0.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7
psutil-5.7.0.dist-info/RECORD,,

Просмотреть файл

@ -1,5 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.30.0)
Generator: bdist_wheel (0.34.2)
Root-Is-Purelib: false
Tag: cp27-cp27m-win_amd64

Просмотреть файл

@ -10,14 +10,14 @@ sensors) in Python. Supported platforms:
- Linux
- Windows
- OSX
- macOS
- FreeBSD
- OpenBSD
- NetBSD
- Sun Solaris
- AIX
Works with Python versions from 2.6 to 3.X.
Works with Python versions from 2.6 to 3.4+.
"""
from __future__ import division
@ -25,37 +25,43 @@ from __future__ import division
import collections
import contextlib
import datetime
import errno
import functools
import os
import signal
import subprocess
import sys
import threading
import time
import traceback
try:
import pwd
except ImportError:
pwd = None
from . import _common
from ._common import AccessDenied
from ._common import deprecated_method
from ._common import Error
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import TimeoutExpired
from ._common import wrap_numbers as _wrap_numbers
from ._compat import callable
from ._common import ZombieProcess
from ._compat import long
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3 as _PY3
from ._common import STATUS_DEAD
from ._common import STATUS_DISK_SLEEP
from ._common import STATUS_IDLE # bsd
from ._common import STATUS_IDLE
from ._common import STATUS_LOCKED
from ._common import STATUS_PARKED
from ._common import STATUS_RUNNING
from ._common import STATUS_SLEEPING
from ._common import STATUS_STOPPED
from ._common import STATUS_TRACING_STOP
from ._common import STATUS_WAITING # bsd
from ._common import STATUS_WAITING
from ._common import STATUS_WAKING
from ._common import STATUS_ZOMBIE
@ -79,19 +85,14 @@ from ._common import AIX
from ._common import BSD
from ._common import FREEBSD # NOQA
from ._common import LINUX
from ._common import MACOS
from ._common import NETBSD # NOQA
from ._common import OPENBSD # NOQA
from ._common import OSX
from ._common import OSX # deprecated alias
from ._common import POSIX # NOQA
from ._common import SUNOS
from ._common import WINDOWS
from ._exceptions import AccessDenied
from ._exceptions import Error
from ._exceptions import NoSuchProcess
from ._exceptions import TimeoutExpired
from ._exceptions import ZombieProcess
if LINUX:
# This is public API and it will be retrieved from _pslinux.py
# via sys.modules.
@ -151,8 +152,12 @@ elif WINDOWS:
from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA
from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA
from ._pswindows import CONN_DELETE_TCB # NOQA
from ._pswindows import IOPRIO_VERYLOW # NOQA
from ._pswindows import IOPRIO_LOW # NOQA
from ._pswindows import IOPRIO_NORMAL # NOQA
from ._pswindows import IOPRIO_HIGH # NOQA
elif OSX:
elif MACOS:
from . import _psosx as _psplatform
elif BSD:
@ -189,6 +194,7 @@ __all__ = [
"STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP",
"STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD",
"STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED",
"STATUS_PARKED",
"CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1",
"CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT",
@ -200,8 +206,8 @@ __all__ = [
"POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED",
"BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "OSX", "POSIX", "SUNOS",
"WINDOWS", "AIX",
"BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX",
"SUNOS", "WINDOWS", "AIX",
# classes
"Process", "Popen",
@ -210,23 +216,26 @@ __all__ = [
"pid_exists", "pids", "process_iter", "wait_procs", # proc
"virtual_memory", "swap_memory", # memory
"cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu
"cpu_stats", # "cpu_freq",
"cpu_stats", # "cpu_freq", "getloadavg"
"net_io_counters", "net_connections", "net_if_addrs", # network
"net_if_stats",
"disk_io_counters", "disk_partitions", "disk_usage", # disk
# "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors
"users", "boot_time", # others
]
__all__.extend(_psplatform.__extra__all__)
__author__ = "Giampaolo Rodola'"
__version__ = "5.4.3"
__version__ = "5.7.0"
version_info = tuple([int(num) for num in __version__.split('.')])
_timer = getattr(time, 'monotonic', time.time)
AF_LINK = _psplatform.AF_LINK
POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED
POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN
_TOTAL_PHYMEM = None
_timer = getattr(time, 'monotonic', time.time)
_LOWEST_PID = None
# Sanity check in case the user messed up with psutil installation
# or did something weird with sys.path. In this case we might end
@ -266,13 +275,9 @@ else:
ret = {}
for pid in pids():
try:
proc = _psplatform.Process(pid)
ppid = proc.ppid()
except (NoSuchProcess, AccessDenied):
# Note: AccessDenied is unlikely to happen.
ret[pid] = _psplatform.Process(pid).ppid()
except (NoSuchProcess, ZombieProcess):
pass
else:
ret[pid] = ppid
return ret
@ -355,7 +360,7 @@ class Process(object):
self._create_time = None
self._gone = False
self._hash = None
self._oneshot_inctx = False
self._lock = threading.RLock()
# used for caching on Windows only (on POSIX ppid may change)
self._ppid = None
# platform-specific modules define an _psplatform.Process
@ -459,40 +464,45 @@ class Process(object):
...
>>>
"""
if self._oneshot_inctx:
# NOOP: this covers the use case where the user enters the
# context twice. Since as_dict() internally uses oneshot()
# I expect that the code below will be a pretty common
# "mistake" that the user will make, so let's guard
# against that:
#
# >>> with p.oneshot():
# ... p.as_dict()
# ...
yield
else:
self._oneshot_inctx = True
try:
# cached in case cpu_percent() is used
self.cpu_times.cache_activate()
# cached in case memory_percent() is used
self.memory_info.cache_activate()
# cached in case parent() is used
self.ppid.cache_activate()
# cached in case username() is used
if POSIX:
self.uids.cache_activate()
# specific implementation cache
self._proc.oneshot_enter()
with self._lock:
if hasattr(self, "_cache"):
# NOOP: this covers the use case where the user enters the
# context twice:
#
# >>> with p.oneshot():
# ... with p.oneshot():
# ...
#
# Also, since as_dict() internally uses oneshot()
# I expect that the code below will be a pretty common
# "mistake" that the user will make, so let's guard
# against that:
#
# >>> with p.oneshot():
# ... p.as_dict()
# ...
yield
finally:
self.cpu_times.cache_deactivate()
self.memory_info.cache_deactivate()
self.ppid.cache_deactivate()
if POSIX:
self.uids.cache_deactivate()
self._proc.oneshot_exit()
self._oneshot_inctx = False
else:
try:
# cached in case cpu_percent() is used
self.cpu_times.cache_activate(self)
# cached in case memory_percent() is used
self.memory_info.cache_activate(self)
# cached in case parent() is used
self.ppid.cache_activate(self)
# cached in case username() is used
if POSIX:
self.uids.cache_activate(self)
# specific implementation cache
self._proc.oneshot_enter()
yield
finally:
self.cpu_times.cache_deactivate(self)
self.memory_info.cache_deactivate(self)
self.ppid.cache_deactivate(self)
if POSIX:
self.uids.cache_deactivate(self)
self._proc.oneshot_exit()
def as_dict(self, attrs=None, ad_value=None):
"""Utility method returning process information as a
@ -543,6 +553,9 @@ class Process(object):
checking whether PID has been reused.
If no parent is known return None.
"""
lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0]
if self.pid == lowest_pid:
return None
ppid = self.ppid()
if ppid is not None:
ctime = self.create_time()
@ -554,6 +567,17 @@ class Process(object):
except NoSuchProcess:
pass
def parents(self):
"""Return the parents of this process as a list of Process
instances. If no parents are known return an empty list.
"""
parents = []
proc = self.parent()
while proc is not None:
parents.append(proc)
proc = proc.parent()
return parents
def is_running(self):
"""Return whether this process is running.
It also checks if PID has been reused by another process in
@ -751,7 +775,7 @@ class Process(object):
"""
return self._proc.io_counters()
# Linux and Windows >= Vista only
# Linux and Windows
if hasattr(_psplatform.Process, "ionice_get"):
def ionice(self, ioclass=None, value=None):
@ -802,9 +826,6 @@ class Process(object):
(and set).
(Windows, Linux and BSD only).
"""
# Automatically remove duplicates both on get and
# set (for get it's not really necessary, it's
# just for extra safety).
if cpus is None:
return list(set(self._proc.cpu_affinity_get()))
else:
@ -828,7 +849,7 @@ class Process(object):
"""
return self._proc.cpu_num()
# Linux, OSX and Windows only
# Linux, macOS, Windows, Solaris, AIX
if hasattr(_psplatform.Process, "environ"):
def environ(self):
@ -1032,7 +1053,7 @@ class Process(object):
namedtuple representing the accumulated process time, in
seconds.
This is similar to os.times() but per-process.
On OSX and Windows children_user and children_system are
On macOS and Windows children_user and children_system are
always set to 0.
"""
return self._proc.cpu_times()
@ -1054,7 +1075,7 @@ class Process(object):
def memory_full_info(self):
"""This method returns the same information as memory_info(),
plus, on some platform (Linux, OSX, Windows), also provides
plus, on some platform (Linux, macOS, Windows), also provides
additional metrics (USS, PSS and swap).
The additional metrics provide a better representation of actual
process memory usage.
@ -1098,7 +1119,6 @@ class Process(object):
return (value / float(total_phymem)) * 100
if hasattr(_psplatform.Process, "memory_maps"):
# Available everywhere except OpenBSD and NetBSD.
def memory_maps(self, grouped=True):
"""Return process' mapped memory regions as a list of namedtuples
whose fields are variable depending on the platform.
@ -1170,18 +1190,16 @@ class Process(object):
"calling process (os.getpid()) instead of PID 0")
try:
os.kill(self.pid, sig)
except OSError as err:
if err.errno == errno.ESRCH:
if OPENBSD and pid_exists(self.pid):
# We do this because os.kill() lies in case of
# zombie processes.
raise ZombieProcess(self.pid, self._name, self._ppid)
else:
self._gone = True
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
except ProcessLookupError:
if OPENBSD and pid_exists(self.pid):
# We do this because os.kill() lies in case of
# zombie processes.
raise ZombieProcess(self.pid, self._name, self._ppid)
else:
self._gone = True
raise NoSuchProcess(self.pid, self._name)
except PermissionError:
raise AccessDenied(self.pid, self._name)
@_assert_pid_not_reused
def send_signal(self, sig):
@ -1193,16 +1211,7 @@ class Process(object):
if POSIX:
self._send_signal(sig)
else: # pragma: no cover
if sig == signal.SIGTERM:
self._proc.kill()
# py >= 2.7
elif sig in (getattr(signal, "CTRL_C_EVENT", object()),
getattr(signal, "CTRL_BREAK_EVENT", object())):
self._proc.send_signal(sig)
else:
raise ValueError(
"only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
"are supported on Windows")
self._proc.send_signal(sig)
@_assert_pid_not_reused
def suspend(self):
@ -1250,6 +1259,8 @@ class Process(object):
def wait(self, timeout=None):
"""Wait for process to terminate and, if process is a children
of os.getpid(), also return its exit code, else None.
On Windows there's no such limitation (exit code is always
returned).
If the process is already terminated immediately return None
instead of raising NoSuchProcess.
@ -1301,7 +1312,7 @@ class Popen(Process):
http://bugs.python.org/issue6973.
For a complete documentation refer to:
http://docs.python.org/library/subprocess.html
http://docs.python.org/3/library/subprocess.html
"""
def __init__(self, *args, **kwargs):
@ -1357,7 +1368,7 @@ class Popen(Process):
_as_dict_attrnames = set(
[x for x in dir(Process) if not x.startswith('_') and x not in
['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
'is_running', 'as_dict', 'parent', 'children', 'rlimit',
'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit',
'memory_info_ex', 'oneshot']])
@ -1368,7 +1379,10 @@ _as_dict_attrnames = set(
def pids():
"""Return a list of current running PIDs."""
return _psplatform.pids()
global _LOWEST_PID
ret = sorted(_psplatform.pids())
_LOWEST_PID = ret[0]
return ret
def pid_exists(pid):
@ -1390,6 +1404,7 @@ def pid_exists(pid):
_pmap = {}
_lock = threading.Lock()
def process_iter(attrs=None, ad_value=None):
@ -1417,21 +1432,26 @@ def process_iter(attrs=None, ad_value=None):
proc = Process(pid)
if attrs is not None:
proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value)
_pmap[proc.pid] = proc
with _lock:
_pmap[proc.pid] = proc
return proc
def remove(pid):
_pmap.pop(pid, None)
with _lock:
_pmap.pop(pid, None)
a = set(pids())
b = set(_pmap.keys())
new_pids = a - b
gone_pids = b - a
for pid in gone_pids:
remove(pid)
for pid, proc in sorted(list(_pmap.items()) +
list(dict.fromkeys(new_pids).items())):
with _lock:
ls = sorted(list(_pmap.items()) +
list(dict.fromkeys(new_pids).items()))
for pid, proc in ls:
try:
if proc is None: # new process
yield add(pid)
@ -1505,6 +1525,7 @@ def wait_procs(procs, timeout=None, callback=None):
pass
else:
if returncode is not None or not proc.is_running():
# Set new Process instance attribute.
proc.returncode = returncode
gone.add(proc)
if callback is not None:
@ -1611,14 +1632,12 @@ try:
except Exception:
# Don't want to crash at import time.
_last_cpu_times = None
traceback.print_exc()
try:
_last_per_cpu_times = cpu_times(percpu=True)
except Exception:
# Don't want to crash at import time.
_last_per_cpu_times = None
traceback.print_exc()
def _cpu_tot_time(times):
@ -1656,6 +1675,27 @@ def _cpu_busy_time(times):
return busy
def _cpu_times_deltas(t1, t2):
assert t1._fields == t2._fields, (t1, t2)
field_deltas = []
for field in _psplatform.scputimes._fields:
field_delta = getattr(t2, field) - getattr(t1, field)
# CPU times are always supposed to increase over time
# or at least remain the same and that's because time
# cannot go backwards.
# Surprisingly sometimes this might not be the case (at
# least on Windows and Linux), see:
# https://github.com/giampaolo/psutil/issues/392
# https://github.com/giampaolo/psutil/issues/645
# https://github.com/giampaolo/psutil/issues/1210
# Trim negative deltas to zero to ignore decreasing fields.
# top does the same. Reference:
# https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063
field_delta = max(0, field_delta)
field_deltas.append(field_delta)
return _psplatform.scputimes(*field_deltas)
def cpu_percent(interval=None, percpu=False):
"""Return a float representing the current system-wide CPU
utilization as a percentage.
@ -1698,18 +1738,11 @@ def cpu_percent(interval=None, percpu=False):
raise ValueError("interval is not positive (got %r)" % interval)
def calculate(t1, t2):
t1_all = _cpu_tot_time(t1)
t1_busy = _cpu_busy_time(t1)
times_delta = _cpu_times_deltas(t1, t2)
t2_all = _cpu_tot_time(t2)
t2_busy = _cpu_busy_time(t2)
all_delta = _cpu_tot_time(times_delta)
busy_delta = _cpu_busy_time(times_delta)
# this usually indicates a float precision issue
if t2_busy <= t1_busy:
return 0.0
busy_delta = t2_busy - t1_busy
all_delta = t2_all - t1_all
try:
busy_perc = (busy_delta / all_delta) * 100
except ZeroDivisionError:
@ -1778,28 +1811,18 @@ def cpu_times_percent(interval=None, percpu=False):
def calculate(t1, t2):
nums = []
all_delta = _cpu_tot_time(t2) - _cpu_tot_time(t1)
for field in t1._fields:
field_delta = getattr(t2, field) - getattr(t1, field)
try:
field_perc = (100 * field_delta) / all_delta
except ZeroDivisionError:
field_perc = 0.0
times_delta = _cpu_times_deltas(t1, t2)
all_delta = _cpu_tot_time(times_delta)
# "scale" is the value to multiply each delta with to get percentages.
# We use "max" to avoid division by zero (if all_delta is 0, then all
# fields are 0 so percentages will be 0 too. all_delta cannot be a
# fraction because cpu times are integers)
scale = 100.0 / max(1, all_delta)
for field_delta in times_delta:
field_perc = field_delta * scale
field_perc = round(field_perc, 1)
# CPU times are always supposed to increase over time
# or at least remain the same and that's because time
# cannot go backwards.
# Surprisingly sometimes this might not be the case (at
# least on Windows and Linux), see:
# https://github.com/giampaolo/psutil/issues/392
# https://github.com/giampaolo/psutil/issues/645
# I really don't know what to do about that except
# forcing the value to 0 or 100.
if field_perc > 100.0:
field_perc = 100.0
# `<=` because `-0.0 == 0.0` evaluates to True
elif field_perc <= 0.0:
field_perc = 0.0
# make sure we don't return negative values or values over 100%
field_perc = min(max(0.0, field_perc), 100.0)
nums.append(field_perc)
return _psplatform.scputimes(*nums)
@ -1862,18 +1885,41 @@ if hasattr(_psplatform, "cpu_freq"):
return ret[0]
else:
currs, mins, maxs = 0.0, 0.0, 0.0
set_none = False
for cpu in ret:
currs += cpu.current
# On Linux if /proc/cpuinfo is used min/max are set
# to None.
if LINUX and cpu.min is None:
set_none = True
continue
mins += cpu.min
maxs += cpu.max
current = currs / num_cpus
min_ = mins / num_cpus
max_ = maxs / num_cpus
if set_none:
min_ = max_ = None
else:
min_ = mins / num_cpus
max_ = maxs / num_cpus
return _common.scpufreq(current, min_, max_)
__all__.append("cpu_freq")
if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"):
# Perform this hasattr check once on import time to either use the
# platform based code or proxy straight from the os module.
if hasattr(os, "getloadavg"):
getloadavg = os.getloadavg
else:
getloadavg = _psplatform.getloadavg
__all__.append("getloadavg")
# =====================================================================
# --- system memory related functions
# =====================================================================
@ -1899,9 +1945,9 @@ def virtual_memory():
- used:
memory used, calculated differently depending on the platform and
designed for informational purposes only:
OSX: active + inactive + wired
macOS: active + wired
BSD: active + wired + cached
LINUX: total - free
Linux: total - free
- free:
memory not being used at all (zeroed) that is readily available;
@ -1919,10 +1965,10 @@ def virtual_memory():
- buffers (BSD, Linux):
cache for things like file system metadata.
- cached (BSD, OSX):
- cached (BSD, macOS):
cache for various things.
- wired (OSX, BSD):
- wired (macOS, BSD):
memory that is marked to always stay in RAM. It is never moved to disk.
- shared (BSD):
@ -2011,7 +2057,8 @@ def disk_io_counters(perdisk=False, nowrap=True):
On recent Windows versions 'diskperf -y' command may need to be
executed first otherwise this function won't find any disk.
"""
rawdict = _psplatform.disk_io_counters()
kwargs = dict(perdisk=perdisk) if LINUX else {}
rawdict = _psplatform.disk_io_counters(**kwargs)
if not rawdict:
return {} if perdisk else None
if nowrap:
@ -2047,7 +2094,7 @@ def net_io_counters(pernic=False, nowrap=True):
- errout: total number of errors while sending
- dropin: total number of incoming packets which were dropped
- dropout: total number of outgoing packets which were dropped
(always 0 on OSX and BSD)
(always 0 on macOS and BSD)
If *pernic* is True return the same information for every
network interface installed on the system as a dictionary
@ -2103,7 +2150,7 @@ def net_connections(kind='inet'):
| all | the sum of all the possible families and protocols |
+------------+----------------------------------------------------+
On OSX this function requires root privileges.
On macOS this function requires root privileges.
"""
return _psplatform.net_connections(kind)
@ -2152,7 +2199,7 @@ def net_if_addrs():
separator = ":" if POSIX else "-"
while addr.count(separator) < 5:
addr += "%s00" % separator
ret[name].append(_common.snic(fam, addr, mask, broadcast, ptp))
ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp))
return dict(ret)
@ -2176,7 +2223,7 @@ def net_if_stats():
# =====================================================================
# Linux
# Linux, macOS
if hasattr(_psplatform, "sensors_temperatures"):
def sensors_temperatures(fahrenheit=False):
@ -2214,7 +2261,7 @@ if hasattr(_psplatform, "sensors_temperatures"):
__all__.append("sensors_temperatures")
# Linux
# Linux, macOS
if hasattr(_psplatform, "sensors_fans"):
def sensors_fans():
@ -2227,7 +2274,7 @@ if hasattr(_psplatform, "sensors_fans"):
__all__.append("sensors_fans")
# Linux, Windows, FreeBSD, OSX
# Linux, Windows, FreeBSD, macOS
if hasattr(_psplatform, "sensors_battery"):
def sensors_battery():
@ -2294,19 +2341,16 @@ if WINDOWS:
def test(): # pragma: no cover
"""List info of all currently running processes emulating ps aux
output.
"""
from ._common import bytes2human
from ._compat import get_terminal_size
today_day = datetime.date.today()
templ = "%-10s %5s %4s %7s %7s %-13s %5s %7s %s"
attrs = ['pid', 'memory_percent', 'name', 'cpu_times', 'create_time',
'memory_info']
if POSIX:
attrs.append('uids')
attrs.append('terminal')
print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "TTY", "START", "TIME",
"COMMAND"))
for p in process_iter(attrs=attrs, ad_value=''):
templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s"
attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times',
'create_time', 'memory_info', 'status', 'nice', 'username']
print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE",
"STATUS", "START", "TIME", "CMDLINE"))
for p in process_iter(attrs, ad_value=None):
if p.info['create_time']:
ctime = datetime.datetime.fromtimestamp(p.info['create_time'])
if ctime.date() == today_day:
@ -2315,30 +2359,46 @@ def test(): # pragma: no cover
ctime = ctime.strftime("%b%d")
else:
ctime = ''
cputime = time.strftime("%M:%S",
time.localtime(sum(p.info['cpu_times'])))
try:
user = p.username()
except Error:
user = ''
if WINDOWS and '\\' in user:
if p.info['cpu_times']:
cputime = time.strftime("%M:%S",
time.localtime(sum(p.info['cpu_times'])))
else:
cputime = ''
user = p.info['username'] or ''
if not user and POSIX:
try:
user = p.uids()[0]
except Error:
pass
if user and WINDOWS and '\\' in user:
user = user.split('\\')[1]
vms = p.info['memory_info'] and \
int(p.info['memory_info'].vms / 1024) or '?'
rss = p.info['memory_info'] and \
int(p.info['memory_info'].rss / 1024) or '?'
memp = p.info['memory_percent'] and \
round(p.info['memory_percent'], 1) or '?'
print(templ % (
user = user[:9]
vms = bytes2human(p.info['memory_info'].vms) if \
p.info['memory_info'] is not None else ''
rss = bytes2human(p.info['memory_info'].rss) if \
p.info['memory_info'] is not None else ''
memp = round(p.info['memory_percent'], 1) if \
p.info['memory_percent'] is not None else ''
nice = int(p.info['nice']) if p.info['nice'] else ''
if p.info['cmdline']:
cmdline = ' '.join(p.info['cmdline'])
else:
cmdline = p.info['name']
status = p.info['status'][:5] if p.info['status'] else ''
line = templ % (
user[:10],
p.info['pid'],
memp,
vms,
rss,
p.info.get('terminal', '') or '?',
nice,
status,
ctime,
cputime,
p.info['name'].strip() or '?'))
cmdline)
print(line[:get_terminal_size()[0]])
del memoize, memoize_when_activated, division, deprecated_method

Просмотреть файл

@ -7,7 +7,7 @@
# Note: this module is imported by setup.py so it should not import
# psutil or third-party modules.
from __future__ import division
from __future__ import division, print_function
import contextlib
import errno
@ -23,6 +23,7 @@ from collections import namedtuple
from socket import AF_INET
from socket import SOCK_DGRAM
from socket import SOCK_STREAM
try:
from socket import AF_INET6
except ImportError:
@ -37,14 +38,14 @@ if sys.version_info >= (3, 4):
else:
enum = None
# can't take it from _common.py as this script is imported by setup.py
PY3 = sys.version_info[0] == 3
__all__ = [
# constants
'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'OSX', 'POSIX', 'SUNOS',
'WINDOWS',
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
# OS constants
'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX',
'SUNOS', 'WINDOWS',
# connection constants
'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED',
'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN',
@ -55,15 +56,20 @@ __all__ = [
'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED',
'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED',
'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL',
'STATUS_WAKING', 'STATUS_ZOMBIE',
'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED',
# other constants
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
# named tuples
'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile',
'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart',
'sdiskusage', 'snetio', 'snic', 'snicstats', 'sswap', 'suser',
'sdiskusage', 'snetio', 'snicaddr', 'snicstats', 'sswap', 'suser',
# utility functions
'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
'parse_environ_block', 'path_exists_strict', 'usage_percent',
'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
'bytes2human', 'conn_to_ntuple', 'debug',
# shell utils
'hilite', 'term_supports_colors', 'print_color',
]
@ -75,12 +81,13 @@ __all__ = [
POSIX = os.name == "posix"
WINDOWS = os.name == "nt"
LINUX = sys.platform.startswith("linux")
OSX = sys.platform.startswith("darwin")
MACOS = sys.platform.startswith("darwin")
OSX = MACOS # deprecated alias
FREEBSD = sys.platform.startswith("freebsd")
OPENBSD = sys.platform.startswith("openbsd")
NETBSD = sys.platform.startswith("netbsd")
BSD = FREEBSD or OPENBSD or NETBSD
SUNOS = sys.platform.startswith("sunos") or sys.platform.startswith("solaris")
SUNOS = sys.platform.startswith(("sunos", "solaris"))
AIX = sys.platform.startswith("aix")
@ -99,10 +106,11 @@ STATUS_ZOMBIE = "zombie"
STATUS_DEAD = "dead"
STATUS_WAKE_KILL = "wake-kill"
STATUS_WAKING = "waking"
STATUS_IDLE = "idle" # FreeBSD, OSX
STATUS_IDLE = "idle" # Linux, macOS, FreeBSD
STATUS_LOCKED = "locked" # FreeBSD
STATUS_WAITING = "waiting" # FreeBSD
STATUS_SUSPENDED = "suspended" # NetBSD
STATUS_PARKED = "parked" # Linux
# Process.connections() and psutil.net_connections()
CONN_ESTABLISHED = "ESTABLISHED"
@ -182,7 +190,8 @@ suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid'])
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status', 'pid'])
# psutil.net_if_addrs()
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast', 'ptp'])
snicaddr = namedtuple('snicaddr',
['family', 'address', 'netmask', 'broadcast', 'ptp'])
# psutil.net_if_stats()
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
# psutil.cpu_stats()
@ -195,7 +204,7 @@ shwtemp = namedtuple(
'shwtemp', ['label', 'current', 'high', 'critical'])
# psutil.sensors_battery()
sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged'])
# psutil.sensors_battery()
# psutil.sensors_fans()
sfan = namedtuple('sfan', ['label', 'current'])
# --- for Process methods
@ -253,7 +262,109 @@ if AF_UNIX is not None:
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
})
del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
# =====================================================================
# --- Exceptions
# =====================================================================
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
__module__ = 'psutil'
def __init__(self, msg=""):
Exception.__init__(self, msg)
self.msg = msg
def __repr__(self):
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
return ret.strip()
__str__ = __repr__
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists.
"""
__module__ = 'psutil'
def __init__(self, pid, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
def __path__(self):
return 'xxx'
class ZombieProcess(NoSuchProcess):
"""Exception raised when querying a zombie process. This is
raised on macOS, BSD and Solaris only, and not always: depending
on the query the OS may be able to succeed anyway.
On Linux all zombie processes are querable (hence this is never
raised). Windows doesn't have zombie processes.
"""
__module__ = 'psutil'
def __init__(self, pid, name=None, ppid=None, msg=None):
NoSuchProcess.__init__(self, msg)
self.pid = pid
self.ppid = ppid
self.name = name
self.msg = msg
if msg is None:
args = ["pid=%s" % pid]
if name:
args.append("name=%s" % repr(self.name))
if ppid:
args.append("ppid=%s" % self.ppid)
details = "(%s)" % ", ".join(args)
self.msg = "process still exists but it's a zombie " + details
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
__module__ = 'psutil'
def __init__(self, pid=None, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
__module__ = 'psutil'
def __init__(self, seconds, pid=None, name=None):
Error.__init__(self, "timeout after %s seconds" % seconds)
self.seconds = seconds
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg += " (pid=%s)" % self.pid
# ===================================================================
@ -261,15 +372,15 @@ del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
# ===================================================================
def usage_percent(used, total, _round=None):
def usage_percent(used, total, round_=None):
"""Calculate percentage usage of 'used' against 'total'."""
try:
ret = (used / total) * 100
ret = (float(used) / total) * 100
except ZeroDivisionError:
ret = 0.0 if isinstance(used, float) or isinstance(total, float) else 0
if _round is not None:
return round(ret, _round)
return 0.0
else:
if round_ is not None:
ret = round(ret, round_)
return ret
@ -324,7 +435,7 @@ def memoize_when_activated(fun):
1
>>>
>>> # activated
>>> foo.cache_activate()
>>> foo.cache_activate(self)
>>> foo()
1
>>> foo()
@ -333,26 +444,30 @@ def memoize_when_activated(fun):
"""
@functools.wraps(fun)
def wrapper(self):
if not wrapper.cache_activated:
try:
# case 1: we previously entered oneshot() ctx
ret = self._cache[fun]
except AttributeError:
# case 2: we never entered oneshot() ctx
return fun(self)
else:
try:
ret = cache[fun]
except KeyError:
ret = cache[fun] = fun(self)
return ret
except KeyError:
# case 3: we entered oneshot() ctx but there's no cache
# for this entry yet
ret = self._cache[fun] = fun(self)
return ret
def cache_activate():
"""Activate cache."""
wrapper.cache_activated = True
def cache_activate(proc):
"""Activate cache. Expects a Process instance. Cache will be
stored as a "_cache" instance attribute."""
proc._cache = {}
def cache_deactivate():
def cache_deactivate(proc):
"""Deactivate and clear cache."""
wrapper.cache_activated = False
cache.clear()
try:
del proc._cache
except AttributeError:
pass
cache = {}
wrapper.cache_activated = False
wrapper.cache_activate = cache_activate
wrapper.cache_deactivate = cache_deactivate
return wrapper
@ -439,7 +554,7 @@ def sockfam_to_enum(num):
else: # pragma: no cover
try:
return socket.AddressFamily(num)
except (ValueError, AttributeError):
except ValueError:
return num
@ -451,11 +566,30 @@ def socktype_to_enum(num):
return num
else: # pragma: no cover
try:
return socket.AddressType(num)
except (ValueError, AttributeError):
return socket.SocketKind(num)
except ValueError:
return num
def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None):
"""Convert a raw connection tuple to a proper ntuple."""
if fam in (socket.AF_INET, AF_INET6):
if laddr:
laddr = addr(*laddr)
if raddr:
raddr = addr(*raddr)
if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6):
status = status_map.get(status, CONN_NONE)
else:
status = CONN_NONE # ignore whatever C returned to us
fam = sockfam_to_enum(fam)
type_ = socktype_to_enum(type_)
if pid is None:
return pconn(fd, fam, type_, laddr, raddr, status)
else:
return sconn(fd, fam, type_, laddr, raddr, status, pid)
def deprecated_method(replacement):
"""A decorator which can be used to mark a method as deprecated
'replcement' is the method name which will be called instead.
@ -468,7 +602,7 @@ def deprecated_method(replacement):
@functools.wraps(fun)
def inner(self, *args, **kwargs):
warnings.warn(msg, category=FutureWarning, stacklevel=2)
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return getattr(self, replacement)(*args, **kwargs)
return inner
return outer
@ -573,3 +707,140 @@ def wrap_numbers(input_dict, name):
_wn = _WrapNumbers()
wrap_numbers.cache_clear = _wn.cache_clear
wrap_numbers.cache_info = _wn.cache_info
def open_binary(fname, **kwargs):
return open(fname, "rb", **kwargs)
def open_text(fname, **kwargs):
"""On Python 3 opens a file in text mode by using fs encoding and
a proper en/decoding errors handler.
On Python 2 this is just an alias for open(name, 'rt').
"""
if PY3:
# See:
# https://github.com/giampaolo/psutil/issues/675
# https://github.com/giampaolo/psutil/pull/733
kwargs.setdefault('encoding', ENCODING)
kwargs.setdefault('errors', ENCODING_ERRS)
return open(fname, "rt", **kwargs)
def bytes2human(n, format="%(value).1f%(symbol)s"):
"""Used by various scripts. See:
http://goo.gl/zeJZl
>>> bytes2human(10000)
'9.8K'
>>> bytes2human(100001221)
'95.4M'
"""
symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols[1:]):
prefix[s] = 1 << (i + 1) * 10
for symbol in reversed(symbols[1:]):
if n >= prefix[symbol]:
value = float(n) / prefix[symbol]
return format % locals()
return format % dict(symbol=symbols[0], value=n)
def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH
if PY3:
def decode(s):
return s.decode(encoding=ENCODING, errors=ENCODING_ERRS)
else:
def decode(s):
return s
# =====================================================================
# --- shell utils
# =====================================================================
@memoize
def term_supports_colors(file=sys.stdout):
if os.name == 'nt':
return True
try:
import curses
assert file.isatty()
curses.setupterm()
assert curses.tigetnum("colors") > 0
except Exception:
return False
else:
return True
def hilite(s, color="green", bold=False):
"""Return an highlighted version of 'string'."""
if not term_supports_colors():
return s
attr = []
colors = dict(green='32', red='91', brown='33')
colors[None] = '29'
try:
color = colors[color]
except KeyError:
raise ValueError("invalid color %r; choose between %r" % (
list(colors.keys())))
attr.append(color)
if bold:
attr.append('1')
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s)
def print_color(s, color="green", bold=False, file=sys.stdout):
"""Print a colorized version of string."""
if not term_supports_colors():
print(s, file=file)
elif POSIX:
print(hilite(s, color, bold), file=file)
else:
import ctypes
DEFAULT_COLOR = 7
GetStdHandle = ctypes.windll.Kernel32.GetStdHandle
SetConsoleTextAttribute = \
ctypes.windll.Kernel32.SetConsoleTextAttribute
colors = dict(green=2, red=4, brown=6)
colors[None] = DEFAULT_COLOR
try:
color = colors[color]
except KeyError:
raise ValueError("invalid color %r; choose between %r" % (
color, list(colors.keys())))
if bold and color <= 7:
color += 8
handle_id = -12 if file is sys.stderr else -11
GetStdHandle.restype = ctypes.c_ulong
handle = GetStdHandle(handle_id)
SetConsoleTextAttribute(handle, color)
try:
print(s, file=file)
finally:
SetConsoleTextAttribute(handle, DEFAULT_COLOR)
if bool(os.getenv('PSUTIL_DEBUG', 0)):
import inspect
def debug(msg):
"""If PSUTIL_DEBUG env var is set, print a debug message to stderr."""
fname, lineno, func_name, lines, index = inspect.getframeinfo(
inspect.currentframe().f_back)
print("psutil-debug [%s:%s]> %s" % (fname, lineno, msg),
file=sys.stderr)
else:
def debug(msg):
pass

Просмотреть файл

@ -5,12 +5,15 @@
"""Module which provides compatibility with older Python versions."""
import collections
import errno
import functools
import os
import sys
__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
"callable", "lru_cache", "which"]
"lru_cache", "which", "get_terminal_size",
"FileNotFoundError", "PermissionError", "ProcessLookupError",
"InterruptedError", "ChildProcessError", "FileExistsError"]
PY3 = sys.version_info[0] == 3
@ -38,12 +41,84 @@ else:
return s
# removed in 3.0, reintroduced in 3.2
try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
# --- exceptions
if PY3:
FileNotFoundError = FileNotFoundError # NOQA
PermissionError = PermissionError # NOQA
ProcessLookupError = ProcessLookupError # NOQA
InterruptedError = InterruptedError # NOQA
ChildProcessError = ChildProcessError # NOQA
FileExistsError = FileExistsError # NOQA
else:
# https://github.com/PythonCharmers/python-future/blob/exceptions/
# src/future/types/exceptions/pep3151.py
import platform
_singleton = object()
def instance_checking_exception(base_exception=Exception):
def wrapped(instance_checker):
class TemporaryClass(base_exception):
def __init__(self, *args, **kwargs):
if len(args) == 1 and isinstance(args[0], TemporaryClass):
unwrap_me = args[0]
for attr in dir(unwrap_me):
if not attr.startswith('__'):
setattr(self, attr, getattr(unwrap_me, attr))
else:
super(TemporaryClass, self).__init__(*args, **kwargs)
class __metaclass__(type):
def __instancecheck__(cls, inst):
return instance_checker(inst)
def __subclasscheck__(cls, classinfo):
value = sys.exc_info()[1]
return isinstance(value, cls)
TemporaryClass.__name__ = instance_checker.__name__
TemporaryClass.__doc__ = instance_checker.__doc__
return TemporaryClass
return wrapped
@instance_checking_exception(EnvironmentError)
def FileNotFoundError(inst):
return getattr(inst, 'errno', _singleton) == errno.ENOENT
@instance_checking_exception(EnvironmentError)
def ProcessLookupError(inst):
return getattr(inst, 'errno', _singleton) == errno.ESRCH
@instance_checking_exception(EnvironmentError)
def PermissionError(inst):
return getattr(inst, 'errno', _singleton) in (
errno.EACCES, errno.EPERM)
@instance_checking_exception(EnvironmentError)
def InterruptedError(inst):
return getattr(inst, 'errno', _singleton) == errno.EINTR
@instance_checking_exception(EnvironmentError)
def ChildProcessError(inst):
return getattr(inst, 'errno', _singleton) == errno.ECHILD
@instance_checking_exception(EnvironmentError)
def FileExistsError(inst):
return getattr(inst, 'errno', _singleton) == errno.EEXIST
if platform.python_implementation() != "CPython":
try:
raise OSError(errno.EEXIST, "perm")
except FileExistsError:
pass
except OSError:
raise RuntimeError(
"broken / incompatible Python implementation, see: "
"https://github.com/giampaolo/psutil/issues/1659")
# --- stdlib additions
@ -247,3 +322,24 @@ except ImportError:
if _access_check(name, mode):
return name
return None
# python 3.3
try:
from shutil import get_terminal_size
except ImportError:
def get_terminal_size(fallback=(80, 24)):
try:
import fcntl
import termios
import struct
except ImportError:
return fallback
else:
try:
# This should work on Linux.
res = struct.unpack(
'hh', fcntl.ioctl(1, termios.TIOCGWINSZ, '1234'))
return (res[1], res[0])
except Exception:
return fallback

Просмотреть файл

@ -1,94 +0,0 @@
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
def __init__(self, msg=""):
Exception.__init__(self, msg)
self.msg = msg
def __repr__(self):
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
return ret.strip()
__str__ = __repr__
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists.
"""
def __init__(self, pid, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
class ZombieProcess(NoSuchProcess):
"""Exception raised when querying a zombie process. This is
raised on OSX, BSD and Solaris only, and not always: depending
on the query the OS may be able to succeed anyway.
On Linux all zombie processes are querable (hence this is never
raised). Windows doesn't have zombie processes.
"""
def __init__(self, pid, name=None, ppid=None, msg=None):
NoSuchProcess.__init__(self, msg)
self.pid = pid
self.ppid = ppid
self.name = name
self.msg = msg
if msg is None:
args = ["pid=%s" % pid]
if name:
args.append("name=%s" % repr(self.name))
if ppid:
args.append("ppid=%s" % self.ppid)
details = "(%s)" % ", ".join(args)
self.msg = "process still exists but it's a zombie " + details
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
def __init__(self, pid=None, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
def __init__(self, seconds, pid=None, name=None):
Error.__init__(self, "timeout after %s seconds" % seconds)
self.seconds = seconds
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg += " (pid=%s)" % self.pid

Просмотреть файл

@ -6,31 +6,32 @@
"""AIX platform implementation."""
import errno
import functools
import glob
import os
import re
import subprocess
import sys
from collections import namedtuple
from socket import AF_INET
from . import _common
from . import _psposix
from . import _psutil_aix as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_to_ntuple
from ._common import get_procfs_path
from ._common import memoize_when_activated
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import NoSuchProcess
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = ["PROCFS_PATH"]
@ -42,6 +43,8 @@ __extra__all__ = ["PROCFS_PATH"]
HAS_THREADS = hasattr(cext, "proc_threads")
HAS_NET_IO_COUNTERS = hasattr(cext, "net_io_counters")
HAS_PROC_IO_COUNTERS = hasattr(cext, "proc_io_counters")
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
AF_LINK = cext_posix.AF_LINK
@ -93,21 +96,6 @@ pfullmem = pmem
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
# psutil.virtual_memory()
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
# --- utils
# =====================================================================
def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH
# =====================================================================
@ -117,7 +105,7 @@ def get_procfs_path():
def virtual_memory():
total, avail, free, pinned, inuse = cext.virtual_mem()
percent = usage_percent((total - avail), total, _round=1)
percent = usage_percent((total - avail), total, round_=1)
return svmem(total, avail, percent, inuse, free)
@ -125,7 +113,7 @@ def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
total, free, sin, sout = cext.swap_mem()
used = total - free
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sswap(total, used, free, percent, sin, sout)
@ -212,7 +200,9 @@ def disk_partitions(all=False):
net_if_addrs = cext_posix.net_if_addrs
net_io_counters = cext.net_io_counters
if HAS_NET_IO_COUNTERS:
net_io_counters = cext.net_io_counters
def net_connections(kind, _pid=-1):
@ -225,27 +215,17 @@ def net_connections(kind, _pid=-1):
% (kind, ', '.join([repr(x) for x in cmap])))
families, types = _common.conn_tmap[kind]
rawlist = cext.net_connections(_pid)
ret = set()
ret = []
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
if fam not in families:
continue
if type_ not in types:
continue
status = TCP_STATUSES[status]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type_ = socktype_to_enum(type_)
if _pid == -1:
nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
else:
nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
ret.add(nt)
return list(ret)
nt = conn_to_ntuple(fd, fam, type_, laddr, raddr, status,
TCP_STATUSES, pid=pid if _pid == -1 else None)
ret.append(nt)
return ret
def net_if_stats():
@ -269,7 +249,8 @@ def net_if_stats():
stdout, stderr = [x.decode(sys.stdout.encoding)
for x in (stdout, stderr)]
if p.returncode == 0:
re_result = re.search("Running: (\d+) Mbps.*?(\w+) Duplex", stdout)
re_result = re.search(
r"Running: (\d+) Mbps.*?(\w+) Duplex", stdout)
if re_result is not None:
speed = int(re_result.group(1))
duplex = re_result.group(2)
@ -327,33 +308,27 @@ def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
# support for private module import
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
except (FileNotFoundError, ProcessLookupError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
__slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"]
def __init__(self, pid):
self.pid = pid
@ -362,23 +337,19 @@ class Process(object):
self._procfs_path = get_procfs_path()
def oneshot_enter(self):
self._proc_name_and_args.cache_activate()
self._proc_basic_info.cache_activate()
self._proc_cred.cache_activate()
self._proc_basic_info.cache_activate(self)
self._proc_cred.cache_activate(self)
def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate()
self._proc_basic_info.cache_deactivate()
self._proc_cred.cache_deactivate()
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)
self._proc_basic_info.cache_deactivate(self)
self._proc_cred.cache_deactivate(self)
@wrap_exceptions
@memoize_when_activated
def _proc_basic_info(self):
return cext.proc_basic_info(self.pid, self._procfs_path)
@wrap_exceptions
@memoize_when_activated
def _proc_cred(self):
return cext.proc_cred(self.pid, self._procfs_path)
@ -387,22 +358,25 @@ class Process(object):
def name(self):
if self.pid == 0:
return "swapper"
# note: this is limited to 15 characters
return self._proc_name_and_args()[0].rstrip("\x00")
# note: max 16 characters
return cext.proc_name(self.pid, self._procfs_path).rstrip("\x00")
@wrap_exceptions
def exe(self):
# there is no way to get executable path in AIX other than to guess,
# and guessing is more complex than what's in the wrapping class
exe = self.cmdline()[0]
cmdline = self.cmdline()
if not cmdline:
return ''
exe = cmdline[0]
if os.path.sep in exe:
# relative or absolute path
if not os.path.isabs(exe):
# if cwd has changed, we're out of luck - this may be wrong!
exe = os.path.abspath(os.path.join(self.cwd(), exe))
if (os.path.isabs(exe) and
os.path.isfile(exe) and
os.access(exe, os.X_OK)):
os.path.isfile(exe) and
os.access(exe, os.X_OK)):
return exe
# not found, move to search in PATH using basename only
exe = os.path.basename(exe)
@ -410,13 +384,17 @@ class Process(object):
for path in os.environ["PATH"].split(":"):
possible_exe = os.path.abspath(os.path.join(path, exe))
if (os.path.isfile(possible_exe) and
os.access(possible_exe, os.X_OK)):
os.access(possible_exe, os.X_OK)):
return possible_exe
return ''
@wrap_exceptions
def cmdline(self):
return self._proc_name_and_args()[1].split(' ')
return cext.proc_args(self.pid)
@wrap_exceptions
def environ(self):
return cext.proc_environ(self.pid)
@wrap_exceptions
def create_time(self):
@ -502,11 +480,9 @@ class Process(object):
try:
result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid))
return result.rstrip('/')
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
raise
except FileNotFoundError:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
@wrap_exceptions
def memory_info(self):
@ -534,7 +510,7 @@ class Process(object):
for x in (stdout, stderr)]
if "no such process" in stderr.lower():
raise NoSuchProcess(self.pid, self._name)
procfiles = re.findall("(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout)
procfiles = re.findall(r"(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout)
retlist = []
for fd, path in procfiles:
path = path.strip()
@ -560,14 +536,15 @@ class Process(object):
def wait(self, timeout=None):
return _psposix.wait_pid(self.pid, timeout, self._name)
@wrap_exceptions
def io_counters(self):
try:
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
except OSError:
# if process is terminated, proc_io_counters returns OSError
# instead of NSP
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
raise
return _common.pio(rc, wc, rb, wb)
if HAS_PROC_IO_COUNTERS:
@wrap_exceptions
def io_counters(self):
try:
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
except OSError:
# if process is terminated, proc_io_counters returns OSError
# instead of NSP
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
raise
return _common.pio(rc, wc, rb, wb)

Просмотреть файл

@ -10,26 +10,28 @@ import functools
import os
import xml.etree.ElementTree as ET
from collections import namedtuple
from socket import AF_INET
from collections import defaultdict
from . import _common
from . import _psposix
from . import _psutil_bsd as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import FREEBSD
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NETBSD
from ._common import NoSuchProcess
from ._common import OPENBSD
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import which
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = []
@ -103,6 +105,11 @@ else:
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
AF_LINK = cext_posix.AF_LINK
HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times")
HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads")
HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files')
HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds')
kinfo_proc_map = dict(
ppid=0,
status=1,
@ -188,7 +195,7 @@ def virtual_memory():
shared = int(line.split()[1]) * 1024
avail = inactive + cached + free
used = active + wired + cached
percent = usage_percent((total - avail), total, _round=1)
percent = usage_percent((total - avail), total, round_=1)
return svmem(total, avail, percent, used, free,
active, inactive, buffers, cached, shared, wired)
@ -196,7 +203,7 @@ def virtual_memory():
def swap_memory():
"""System swap memory as (total, used, free, sin, sout) namedtuple."""
total, used, free, sin, sout = cext.swap_mem()
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sswap(total, used, free, percent, sin, sout)
@ -211,7 +218,7 @@ def cpu_times():
return scputimes(user, nice, system, idle, irq)
if hasattr(cext, "per_cpu_times"):
if HAS_PER_CPU_TIMES:
def per_cpu_times():
"""Return system CPU times as a namedtuple"""
ret = []
@ -345,12 +352,18 @@ def net_if_stats():
names = net_io_counters().keys()
ret = {}
for name in names:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
try:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1279
if err.errno != errno.ENODEV:
raise
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
@ -383,22 +396,8 @@ def net_connections(kind):
fd, fam, type, laddr, raddr, status, pid = item
# TODO: apply filter at C level
if fam in families and type in types:
try:
status = TCP_STATUSES[status]
except KeyError:
# XXX: Not sure why this happens. I saw this occurring
# with IPv6 sockets opened by 'vim'. Those sockets
# have a very short lifetime so maybe the kernel
# can't initialize their status?
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES, pid)
ret.add(nt)
return list(ret)
@ -426,6 +425,47 @@ if FREEBSD:
secsleft = minsleft * 60
return _common.sbattery(percent, secsleft, power_plugged)
def sensors_temperatures():
"Return CPU cores temperatures if available, else an empty dict."
ret = defaultdict(list)
num_cpus = cpu_count_logical()
for cpu in range(num_cpus):
try:
current, high = cext.sensors_cpu_temperature(cpu)
if high <= 0:
high = None
name = "Core %s" % cpu
ret["coretemp"].append(
_common.shwtemp(name, current, high, high))
except NotImplementedError:
pass
return ret
def cpu_freq():
"""Return frequency metrics for CPUs. As of Dec 2018 only
CPU 0 appears to be supported by FreeBSD and all other cores
match the frequency of CPU 0.
"""
ret = []
num_cpus = cpu_count_logical()
for cpu in range(num_cpus):
try:
current, available_freq = cext.cpu_frequency(cpu)
except NotImplementedError:
continue
if available_freq:
try:
min_freq = int(available_freq.split(" ")[-1].split("/")[0])
except(IndexError, ValueError):
min_freq = None
try:
max_freq = int(available_freq.split(" ")[0].split("/")[0])
except(IndexError, ValueError):
max_freq = None
ret.append(_common.scpufreq(current, min_freq, max_freq))
return ret
# =====================================================================
# --- other system functions
@ -494,6 +534,14 @@ else:
pid_exists = _psposix.pid_exists
def is_zombie(pid):
try:
st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']]
return st == cext.SZOMB
except Exception:
return False
def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
@ -502,19 +550,19 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError as err:
except ProcessLookupError:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except OSError:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
if err.errno == errno.ESRCH:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
return wrapper
@ -524,30 +572,35 @@ def wrap_exceptions_procfs(inst):
"""Same as above, for routines relying on reading /proc fs."""
try:
yield
except EnvironmentError as err:
except (ProcessLookupError, FileNotFoundError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(inst.pid):
raise NoSuchProcess(inst.pid, inst._name)
else:
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(inst.pid, inst._name)
raise
if not pid_exists(inst.pid):
raise NoSuchProcess(inst.pid, inst._name)
else:
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
except PermissionError:
raise AccessDenied(inst.pid, inst._name)
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid"]
__slots__ = ["pid", "_name", "_ppid", "_cache"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
def _assert_alive(self):
"""Raise NSP if the process disappeared on us."""
# For those C function who do not raise NSP, possibly returning
# incorrect or incomplete result.
cext.proc_name(self.pid)
@wrap_exceptions
@memoize_when_activated
def oneshot(self):
"""Retrieves multiple process info in one shot as a raw tuple."""
@ -556,10 +609,10 @@ class Process(object):
return ret
def oneshot_enter(self):
self.oneshot.cache_activate()
self.oneshot.cache_activate(self)
def oneshot_exit(self):
self.oneshot.cache_deactivate()
self.oneshot.cache_deactivate(self)
@wrap_exceptions
def name(self):
@ -569,6 +622,8 @@ class Process(object):
@wrap_exceptions
def exe(self):
if FREEBSD:
if self.pid == 0:
return '' # else NSP
return cext.proc_exe(self.pid)
elif NETBSD:
if self.pid == 0:
@ -584,7 +639,7 @@ class Process(object):
# cmdline arg (may return None).
cmdline = self.cmdline()
if cmdline:
return which(cmdline[0])
return which(cmdline[0]) or ""
else:
return ""
@ -601,10 +656,14 @@ class Process(object):
return cext.proc_cmdline(self.pid)
except OSError as err:
if err.errno == errno.EINVAL:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
if is_zombie(self.pid):
raise ZombieProcess(self.pid, self._name, self._ppid)
elif not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name, self._ppid)
else:
# XXX: this happens with unicode tests. It means the C
# routine is unable to decode invalid unicode chars.
return []
else:
raise
else:
@ -672,7 +731,7 @@ class Process(object):
@wrap_exceptions
def num_threads(self):
if hasattr(cext, "proc_num_threads"):
if HAS_PROC_NUM_THREADS:
# FreeBSD
return cext.proc_num_threads(self.pid)
else:
@ -694,10 +753,7 @@ class Process(object):
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
if OPENBSD:
# On OpenBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
self._assert_alive()
return retlist
@wrap_exceptions
@ -708,29 +764,16 @@ class Process(object):
if NETBSD:
families, types = conn_tmap[kind]
ret = set()
ret = []
rawlist = cext.net_connections(self.pid)
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
assert pid == self.pid
if fam in families and type in types:
try:
status = TCP_STATUSES[status]
except KeyError:
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.add(nt)
# On NetBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
self._assert_alive()
return list(ret)
families, types = conn_tmap[kind]
@ -738,21 +781,13 @@ class Process(object):
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
status = TCP_STATUSES[status]
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
if OPENBSD:
# On OpenBSD the underlying C function does not raise NSP
# in case the process is gone (and the returned list may
# incomplete).
self.name() # raise NSP if the process disappeared on us
self._assert_alive()
return ret
@wrap_exceptions
@ -789,10 +824,7 @@ class Process(object):
# it into None
if OPENBSD and self.pid == 0:
return None # ...else it would raise EINVAL
elif NETBSD:
with wrap_exceptions_procfs(self):
return os.readlink("/proc/%s/cwd" % self.pid)
elif hasattr(cext, 'proc_open_files'):
elif NETBSD or HAS_PROC_OPEN_FILES:
# FreeBSD < 8 does not support functions based on
# kinfo_getfile() and kinfo_getvmmap()
return cext.proc_cwd(self.pid) or None
@ -811,7 +843,7 @@ class Process(object):
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_open_files'):
if HAS_PROC_OPEN_FILES:
@wrap_exceptions
def open_files(self):
"""Return files opened by process as a list of namedtuples."""
@ -822,15 +854,13 @@ class Process(object):
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_num_fds'):
if HAS_PROC_NUM_FDS:
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
ret = cext.proc_num_fds(self.pid)
if NETBSD:
# On NetBSD the underlying C function does not raise NSP
# in case the process is gone.
self.name() # raise NSP if the process disappeared on us
self._assert_alive()
return ret
else:
num_fds = _not_implemented

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2,30 +2,29 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""OSX platform implementation."""
"""macOS platform implementation."""
import contextlib
import errno
import functools
import os
from socket import AF_INET
from collections import namedtuple
from . import _common
from . import _psposix
from . import _psutil_osx as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
from ._common import ZombieProcess
from ._compat import PermissionError
from ._compat import ProcessLookupError
__extra__all__ = []
@ -103,13 +102,6 @@ svmem = namedtuple(
pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins'])
# psutil.Process.memory_full_info()
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', ))
# psutil.Process.memory_maps(grouped=True)
pmmap_grouped = namedtuple(
'pmmap_grouped',
'path rss private swapped dirtied ref_count shadow_depth')
# psutil.Process.memory_maps(grouped=False)
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
@ -119,10 +111,17 @@ pmmap_ext = namedtuple(
def virtual_memory():
"""System virtual memory as a namedtuple."""
total, active, inactive, wired, free = cext.virtual_mem()
total, active, inactive, wired, free, speculative = cext.virtual_mem()
# This is how Zabbix calculate avail and used mem:
# https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/
# osx/memory.c
# Also see: https://github.com/giampaolo/psutil/issues/1277
avail = inactive + free
used = active + inactive + wired
percent = usage_percent((total - avail), total, _round=1)
used = active + wired
# This is NOT how Zabbix calculates free mem but it matches "free"
# cmdline utility.
free -= speculative
percent = usage_percent((total - avail), total, round_=1)
return svmem(total, avail, percent, used, free,
active, inactive, wired)
@ -130,7 +129,7 @@ def virtual_memory():
def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
total, used, free, sin, sout = cext.swap_mem()
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sswap(total, used, free, percent, sin, sout)
@ -174,7 +173,7 @@ def cpu_stats():
def cpu_freq():
"""Return CPU frequency.
On OSX per-cpu frequency is not supported.
On macOS per-cpu frequency is not supported.
Also, the returned frequency never changes, see:
https://arstechnica.com/civis/viewtopic.php?f=19&t=465002
"""
@ -213,8 +212,7 @@ def disk_partitions(all=False):
def sensors_battery():
"""Return battery information.
"""
"""Return battery information."""
try:
percent, minsleft, power_plugged = cext.sensors_battery()
except NotImplementedError:
@ -241,7 +239,7 @@ net_if_addrs = cext_posix.net_if_addrs
def net_connections(kind='inet'):
"""System-wide network connections."""
# Note: on OSX this will fail with AccessDenied unless
# Note: on macOS this will fail with AccessDenied unless
# the process is owned by root.
ret = []
for pid in pids():
@ -262,12 +260,18 @@ def net_if_stats():
names = net_io_counters().keys()
ret = {}
for name in names:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
try:
mtu = cext_posix.net_if_mtu(name)
isup = cext_posix.net_if_flags(name)
duplex, speed = cext_posix.net_if_duplex_speed(name)
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1279
if err.errno != errno.ENODEV:
raise
else:
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
@ -304,16 +308,16 @@ def users():
def pids():
ls = cext.pids()
if 0 not in ls:
# On certain OSX versions pids() C doesn't return PID 0 but
# On certain macOS versions pids() C doesn't return PID 0 but
# "ps" does and the process is querable via sysctl():
# https://travis-ci.org/giampaolo/psutil/jobs/309619941
try:
Process(0).create_time()
ls.append(0)
ls.insert(0, 0)
except NoSuchProcess:
pass
except AccessDenied:
ls.append(0)
ls.insert(0, 0)
return ls
@ -328,12 +332,12 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError as err:
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
except ProcessLookupError:
raise NoSuchProcess(self.pid, self._name)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except cext.ZombieProcessError:
raise ZombieProcess(self.pid, self._name, self._ppid)
return wrapper
@ -366,13 +370,14 @@ def catch_zombie(proc):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid"]
__slots__ = ["pid", "_name", "_ppid", "_cache"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
@wrap_exceptions
@memoize_when_activated
def _get_kinfo_proc(self):
# Note: should work with all PIDs without permission issues.
@ -380,6 +385,7 @@ class Process(object):
assert len(ret) == len(kinfo_proc_map)
return ret
@wrap_exceptions
@memoize_when_activated
def _get_pidtaskinfo(self):
# Note: should work for PIDs owned by user only.
@ -389,12 +395,12 @@ class Process(object):
return ret
def oneshot_enter(self):
self._get_kinfo_proc.cache_activate()
self._get_pidtaskinfo.cache_activate()
self._get_kinfo_proc.cache_activate(self)
self._get_pidtaskinfo.cache_activate(self)
def oneshot_exit(self):
self._get_kinfo_proc.cache_deactivate()
self._get_pidtaskinfo.cache_deactivate()
self._get_kinfo_proc.cache_deactivate(self)
self._get_pidtaskinfo.cache_deactivate(self)
@wrap_exceptions
def name(self):
@ -516,15 +522,8 @@ class Process(object):
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
return ret
@ -557,15 +556,9 @@ class Process(object):
@wrap_exceptions
def threads(self):
with catch_zombie(self):
rawlist = cext.proc_threads(self.pid)
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def memory_maps(self):
with catch_zombie(self):
return cext.proc_memory_maps(self.pid)

Просмотреть файл

@ -4,7 +4,6 @@
"""Routines common to all posix systems."""
import errno
import glob
import os
import sys
@ -12,10 +11,15 @@ import time
from ._common import memoize
from ._common import sdiskusage
from ._common import TimeoutExpired
from ._common import usage_percent
from ._compat import ChildProcessError
from ._compat import FileNotFoundError
from ._compat import InterruptedError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
from ._compat import unicode
from ._exceptions import TimeoutExpired
__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
@ -32,19 +36,13 @@ def pid_exists(pid):
return True
try:
os.kill(pid, 0)
except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
elif err.errno == errno.EPERM:
# EPERM clearly means there's a process to deny access to
return True
else:
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH) therefore we should never get
# here. If we do let's be explicit in considering this
# an error.
raise err
except ProcessLookupError:
return False
except PermissionError:
# EPERM clearly means there's a process to deny access to
return True
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH)
else:
return True
@ -80,24 +78,20 @@ def wait_pid(pid, timeout=None, proc_name=None):
while True:
try:
retpid, status = waitcall()
except OSError as err:
if err.errno == errno.EINTR:
delay = check_timeout(delay)
continue
elif err.errno == errno.ECHILD:
# This has two meanings:
# - pid is not a child of os.getpid() in which case
# we keep polling until it's gone
# - pid never existed in the first place
# In both cases we'll eventually return None as we
# can't determine its exit status code.
while True:
if pid_exists(pid):
delay = check_timeout(delay)
else:
return
else:
raise
except InterruptedError:
delay = check_timeout(delay)
except ChildProcessError:
# This has two meanings:
# - pid is not a child of os.getpid() in which case
# we keep polling until it's gone
# - pid never existed in the first place
# In both cases we'll eventually return None as we
# can't determine its exit status code.
while True:
if pid_exists(pid):
delay = check_timeout(delay)
else:
return
else:
if retpid == 0:
# WNOHANG was used, pid is still running
@ -156,7 +150,7 @@ def disk_usage(path):
# User usage percent compared to the total amount of space
# the user can use. This number would be higher if compared
# to root's because the user has less space (usually -5%).
usage_percent_user = usage_percent(used, total_user, _round=1)
usage_percent_user = usage_percent(used, total_user, round_=1)
# NB: the percentage is -5% than what shown by df due to
# reserved blocks that we are currently not considering:
@ -176,7 +170,6 @@ def get_terminal_map():
assert name not in ret, name
try:
ret[os.stat(name).st_rdev] = name
except OSError as err:
if err.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
return ret

Просмотреть файл

@ -5,6 +5,7 @@
"""Sun OS Solaris platform implementation."""
import errno
import functools
import os
import socket
import subprocess
@ -16,17 +17,22 @@ from . import _common
from . import _psposix
from . import _psutil_posix as cext_posix
from . import _psutil_sunos as cext
from ._common import AccessDenied
from ._common import AF_INET6
from ._common import debug
from ._common import get_procfs_path
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import b
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import ZombieProcess
__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]
@ -79,7 +85,11 @@ proc_info_map = dict(
nice=4,
num_threads=5,
status=6,
ttynr=7)
ttynr=7,
uid=8,
euid=9,
gid=10,
egid=11)
# =====================================================================
@ -105,16 +115,6 @@ pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# =====================================================================
# --- utils
# =====================================================================
def get_procfs_path():
"""Return updated psutil.PROCFS_PATH constant."""
return sys.modules['psutil'].PROCFS_PATH
# =====================================================================
# --- memory
# =====================================================================
@ -127,7 +127,7 @@ def virtual_memory():
# note: there's no difference on Solaris
free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
used = total - free
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return svmem(total, avail, percent, used, free)
@ -159,7 +159,7 @@ def swap_memory():
total += int(int(t) * 512)
free += int(int(f) * 512)
used = total - free
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sswap(total, used, free, percent,
sin * PAGE_SIZE, sout * PAGE_SIZE)
@ -226,7 +226,12 @@ def disk_partitions(all=False):
# Differently from, say, Linux, we don't have a list of
# common fs types so the best we can do, AFAIK, is to
# filter by filesystem having a total size > 0.
if not disk_usage(mountpoint).total:
try:
if not disk_usage(mountpoint).total:
continue
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1674
debug("skipping %r: %r" % (mountpoint, err))
continue
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
@ -262,6 +267,7 @@ def net_connections(kind, _pid=-1):
continue
if type_ not in types:
continue
# TODO: refactor and use _common.conn_to_ntuple.
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
@ -337,26 +343,26 @@ def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
except (FileNotFoundError, ProcessLookupError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except OSError:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
return wrapper
@ -364,7 +370,7 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid", "_procfs_path"]
__slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"]
def __init__(self, pid):
self.pid = pid
@ -372,26 +378,38 @@ class Process(object):
self._ppid = None
self._procfs_path = get_procfs_path()
def _assert_alive(self):
"""Raise NSP if the process disappeared on us."""
# For those C function who do not raise NSP, possibly returning
# incorrect or incomplete result.
os.stat('%s/%s' % (self._procfs_path, self.pid))
def oneshot_enter(self):
self._proc_name_and_args.cache_activate()
self._proc_basic_info.cache_activate()
self._proc_cred.cache_activate()
self._proc_name_and_args.cache_activate(self)
self._proc_basic_info.cache_activate(self)
self._proc_cred.cache_activate(self)
def oneshot_exit(self):
self._proc_name_and_args.cache_deactivate()
self._proc_basic_info.cache_deactivate()
self._proc_cred.cache_deactivate()
self._proc_name_and_args.cache_deactivate(self)
self._proc_basic_info.cache_deactivate(self)
self._proc_cred.cache_deactivate(self)
@wrap_exceptions
@memoize_when_activated
def _proc_name_and_args(self):
return cext.proc_name_and_args(self.pid, self._procfs_path)
@wrap_exceptions
@memoize_when_activated
def _proc_basic_info(self):
if self.pid == 0 and not \
os.path.exists('%s/%s/psinfo' % (self._procfs_path, self.pid)):
raise AccessDenied(self.pid)
ret = cext.proc_basic_info(self.pid, self._procfs_path)
assert len(ret) == len(proc_info_map)
return ret
@wrap_exceptions
@memoize_when_activated
def _proc_cred(self):
return cext.proc_cred(self.pid, self._procfs_path)
@ -432,27 +450,10 @@ class Process(object):
@wrap_exceptions
def nice_get(self):
# Note #1: for some reason getpriority(3) return ESRCH (no such
# process) for certain low-pid processes, no matter what (even
# as root).
# The process actually exists though, as it has a name,
# creation time, etc.
# The best thing we can do here appears to be raising AD.
# Note: tested on Solaris 11; on Open Solaris 5 everything is
# fine.
#
# Note #2: we also can get niceness from /proc/pid/psinfo
# but it's wrong, see:
# https://github.com/giampaolo/psutil/issues/1082
try:
return cext_posix.getpriority(self.pid)
except EnvironmentError as err:
# 48 is 'operation not supported' but errno does not expose
# it. It occurs for low system pids.
if err.errno in (errno.ENOENT, errno.ESRCH, 48):
if pid_exists(self.pid):
raise AccessDenied(self.pid, self._name)
raise
# Note #1: getpriority(3) doesn't work for realtime processes.
# Psinfo is what ps uses, see:
# https://github.com/giampaolo/psutil/issues/1194
return self._proc_basic_info()[proc_info_map['nice']]
@wrap_exceptions
def nice_set(self, value):
@ -471,12 +472,22 @@ class Process(object):
@wrap_exceptions
def uids(self):
real, effective, saved, _, _, _ = self._proc_cred()
try:
real, effective, saved, _, _, _ = self._proc_cred()
except AccessDenied:
real = self._proc_basic_info()[proc_info_map['uid']]
effective = self._proc_basic_info()[proc_info_map['euid']]
saved = None
return _common.puids(real, effective, saved)
@wrap_exceptions
def gids(self):
_, _, _, real, effective, saved = self._proc_cred()
try:
_, _, _, real, effective, saved = self._proc_cred()
except AccessDenied:
real = self._proc_basic_info()[proc_info_map['gid']]
effective = self._proc_basic_info()[proc_info_map['egid']]
saved = None
return _common.puids(real, effective, saved)
@wrap_exceptions
@ -512,14 +523,11 @@ class Process(object):
try:
return os.readlink(
'%s/%d/path/%d' % (procfs_path, self.pid, x))
except OSError as err:
if err.errno == errno.ENOENT:
hit_enoent = True
continue
raise
except FileNotFoundError:
hit_enoent = True
continue
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
self._assert_alive()
@wrap_exceptions
def cwd(self):
@ -530,11 +538,9 @@ class Process(object):
procfs_path = self._procfs_path
try:
return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid))
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
raise
except FileNotFoundError:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
@wrap_exceptions
def memory_info(self):
@ -581,8 +587,7 @@ class Process(object):
nt = _common.pthread(tid, utime, stime)
ret.append(nt)
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
self._assert_alive()
return ret
@wrap_exceptions
@ -596,18 +601,14 @@ class Process(object):
if os.path.islink(path):
try:
file = os.readlink(path)
except OSError as err:
# ENOENT == file which is gone in the meantime
if err.errno == errno.ENOENT:
hit_enoent = True
continue
raise
except FileNotFoundError:
hit_enoent = True
continue
else:
if isfile_strict(file):
retlist.append(_common.popenfile(file, int(fd)))
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
self._assert_alive()
return retlist
def _get_unix_sockets(self, pid):
@ -707,8 +708,7 @@ class Process(object):
raise
retlist.append((addr, perm, name, rss, anon, locked))
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('%s/%s' % (procfs_path, self.pid))
self._assert_alive()
return retlist
@wrap_exceptions

Двоичные данные
third_party/python/psutil-cp27-none-win_amd64/psutil/_psutil_windows.pyd поставляемый

Двоичный файл не отображается.

Просмотреть файл

@ -8,10 +8,37 @@ import contextlib
import errno
import functools
import os
import signal
import sys
import time
from collections import namedtuple
from . import _common
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import debug
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import isfile_strict
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import parse_environ_block
from ._common import TimeoutExpired
from ._common import usage_percent
from ._compat import long
from ._compat import lru_cache
from ._compat import PY3
from ._compat import unicode
from ._compat import xrange
from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS
from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS
from ._psutil_windows import HIGH_PRIORITY_CLASS
from ._psutil_windows import IDLE_PRIORITY_CLASS
from ._psutil_windows import NORMAL_PRIORITY_CLASS
from ._psutil_windows import REALTIME_PRIORITY_CLASS
try:
from . import _psutil_windows as cext
except ImportError as err:
@ -21,41 +48,13 @@ except ImportError as err:
# 1) we are on an old Windows version
# 2) psutil was installed via pip + wheel
# See: https://github.com/giampaolo/psutil/issues/811
# It must be noted that psutil can still (kind of) work
# on outdated systems if compiled / installed from sources,
# but if we get here it means this this was a wheel (or exe).
msg = "this Windows version is too old (< Windows Vista); "
msg += "psutil 3.4.2 is the latest version which supports Windows "
msg += "2000, XP and 2003 server; it may be possible that psutil "
msg += "will work if compiled from sources though"
msg += "2000, XP and 2003 server"
raise RuntimeError(msg)
else:
raise
from ._common import conn_tmap
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._compat import long
from ._compat import lru_cache
from ._compat import PY3
from ._compat import unicode
from ._compat import xrange
from ._exceptions import AccessDenied
from ._exceptions import NoSuchProcess
from ._exceptions import TimeoutExpired
from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS
from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS
from ._psutil_windows import HIGH_PRIORITY_CLASS
from ._psutil_windows import IDLE_PRIORITY_CLASS
from ._psutil_windows import NORMAL_PRIORITY_CLASS
from ._psutil_windows import REALTIME_PRIORITY_CLASS
if sys.version_info >= (3, 4):
import enum
else:
@ -65,11 +64,14 @@ else:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
__extra__all__ = [
"win_service_iter", "win_service_get",
# Process priority
"ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
"HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",
"NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS",
"CONN_DELETE_TCB",
"AF_LINK",
"HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS",
"REALTIME_PRIORITY_CLASS",
# IO priority
"IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH",
# others
"CONN_DELETE_TCB", "AF_LINK",
]
@ -78,12 +80,8 @@ __extra__all__ = [
# =====================================================================
CONN_DELETE_TCB = "DELETE_TCB"
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
ACCESS_DENIED_ERRSET = frozenset([errno.EPERM, errno.EACCES,
cext.ERROR_ACCESS_DENIED])
NO_SUCH_SERVICE_ERRSET = frozenset([cext.ERROR_INVALID_NAME,
cext.ERROR_SERVICE_DOES_NOT_EXIST])
ERROR_PARTIAL_COPY = 299
PYPY = '__pypy__' in sys.builtin_module_names
if enum is None:
AF_LINK = -1
@ -118,6 +116,19 @@ if enum is not None:
globals().update(Priority.__members__)
if enum is None:
IOPRIO_VERYLOW = 0
IOPRIO_LOW = 1
IOPRIO_NORMAL = 2
IOPRIO_HIGH = 3
else:
class IOPriority(enum.IntEnum):
IOPRIO_VERYLOW = 0
IOPRIO_LOW = 1
IOPRIO_NORMAL = 2
IOPRIO_HIGH = 3
globals().update(IOPriority.__members__)
pinfo_map = dict(
num_handles=0,
ctx_switches=1,
@ -187,7 +198,8 @@ def convert_dos_path(s):
"""
rawdrive = '\\'.join(s.split('\\')[:3])
driveletter = cext.win32_QueryDosDevice(rawdrive)
return os.path.join(driveletter, s[len(rawdrive):])
remainder = s[len(rawdrive):]
return os.path.join(driveletter, remainder)
def py2_strencode(s):
@ -200,7 +212,12 @@ def py2_strencode(s):
if isinstance(s, str):
return s
else:
return s.encode(ENCODING, errors=ENCODING_ERRS)
return s.encode(ENCODING, ENCODING_ERRS)
@memoize
def getpagesize():
return cext.getpagesize()
# =====================================================================
@ -217,7 +234,7 @@ def virtual_memory():
avail = availphys
free = availphys
used = total - avail
percent = usage_percent((total - avail), total, _round=1)
percent = usage_percent((total - avail), total, round_=1)
return svmem(total, avail, percent, used, free)
@ -227,7 +244,7 @@ def swap_memory():
total = mem[2]
free = mem[3]
used = total - free
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sswap(total, used, free, percent, 0, 0)
@ -247,7 +264,7 @@ def disk_usage(path):
path = path.decode(ENCODING, errors="strict")
total, free = cext.disk_usage(path)
used = total - free
percent = usage_percent(used, total, _round=1)
percent = usage_percent(used, total, round_=1)
return _common.sdiskusage(total, used, free, percent)
@ -288,7 +305,7 @@ def cpu_count_logical():
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
"""Return the number of physical CPU cores in the system."""
return cext.cpu_count_phys()
@ -309,6 +326,23 @@ def cpu_freq():
return [_common.scpufreq(float(curr), min_, float(max_))]
_loadavg_inititialized = False
def getloadavg():
"""Return the number of processes in the system run queue averaged
over the last 1, 5, and 15 minutes respectively as a tuple"""
global _loadavg_inititialized
if not _loadavg_inititialized:
cext.init_loadavg_counter()
_loadavg_inititialized = True
# Drop to 2 decimal points which is what Linux does
raw_loads = cext.getloadavg()
return tuple([round(load, 2) for load in raw_loads])
# =====================================================================
# --- network
# =====================================================================
@ -326,17 +360,8 @@ def net_connections(kind, _pid=-1):
ret = set()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
if _pid == -1:
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
else:
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, TCP_STATUSES,
pid=pid if _pid == -1 else None)
ret.add(nt)
return list(ret)
@ -501,14 +526,14 @@ class WindowsService(object):
"""
try:
yield
except WindowsError as err:
if err.errno in ACCESS_DENIED_ERRSET:
except OSError as err:
if is_permission_err(err):
raise AccessDenied(
pid=None, name=self._name,
msg="service %r is not querable (not enough privileges)" %
self._name)
elif err.errno in NO_SUCH_SERVICE_ERRSET or \
err.winerror in NO_SUCH_SERVICE_ERRSET:
elif err.winerror in (cext.ERROR_INVALID_NAME,
cext.ERROR_SERVICE_DOES_NOT_EXIST):
raise NoSuchProcess(
pid=None, name=self._name,
msg="service %r does not exist)" % self._name)
@ -625,27 +650,68 @@ pid_exists = cext.pid_exists
ppid_map = cext.ppid_map # used internally by Process.children()
def is_permission_err(exc):
"""Return True if this is a permission error."""
assert isinstance(exc, OSError), exc
# On Python 2 OSError doesn't always have 'winerror'. Sometimes
# it does, in which case the original exception was WindowsError
# (which is a subclass of OSError).
return exc.errno in (errno.EPERM, errno.EACCES) or \
getattr(exc, "winerror", -1) in (cext.ERROR_ACCESS_DENIED,
cext.ERROR_PRIVILEGE_NOT_HELD)
def convert_oserror(exc, pid=None, name=None):
"""Convert OSError into NoSuchProcess or AccessDenied."""
assert isinstance(exc, OSError), exc
if is_permission_err(exc):
return AccessDenied(pid=pid, name=name)
if exc.errno == errno.ESRCH:
return NoSuchProcess(pid=pid, name=name)
raise exc
def wrap_exceptions(fun):
"""Decorator which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
"""Decorator which converts OSError into NoSuchProcess or AccessDenied."""
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
raise
raise convert_oserror(err, pid=self.pid, name=self._name)
return wrapper
def retry_error_partial_copy(fun):
"""Workaround for https://github.com/giampaolo/psutil/issues/875.
See: https://stackoverflow.com/questions/4457745#4457745
"""
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
delay = 0.0001
times = 33
for x in range(times): # retries for roughly 1 second
try:
return fun(self, *args, **kwargs)
except WindowsError as _:
err = _
if err.winerror == ERROR_PARTIAL_COPY:
time.sleep(delay)
delay = min(delay * 2, 0.04)
continue
else:
raise
else:
msg = "%s retried %s times, converted to AccessDenied as it's " \
"still returning %r" % (fun, times, err)
raise AccessDenied(pid=self.pid, name=self._name, msg=msg)
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name", "_ppid"]
__slots__ = ["pid", "_name", "_ppid", "_cache"]
def __init__(self, pid):
self.pid = pid
@ -655,13 +721,15 @@ class Process(object):
# --- oneshot() stuff
def oneshot_enter(self):
self.oneshot_info.cache_activate()
self._proc_info.cache_activate(self)
self.exe.cache_activate(self)
def oneshot_exit(self):
self.oneshot_info.cache_deactivate()
self._proc_info.cache_deactivate(self)
self.exe.cache_deactivate(self)
@memoize_when_activated
def oneshot_info(self):
def _proc_info(self):
"""Return multiple information about this process as a
raw tuple.
"""
@ -669,7 +737,6 @@ class Process(object):
assert len(ret) == len(pinfo_map)
return ret
@wrap_exceptions
def name(self):
"""Return process name, which on Windows is always the final
part of the executable.
@ -678,37 +745,53 @@ class Process(object):
# and process-hacker.
if self.pid == 0:
return "System Idle Process"
elif self.pid == 4:
if self.pid == 4:
return "System"
else:
try:
# Note: this will fail with AD for most PIDs owned
# by another user but it's faster.
return py2_strencode(os.path.basename(self.exe()))
except AccessDenied:
return py2_strencode(cext.proc_name(self.pid))
return os.path.basename(self.exe())
@wrap_exceptions
@memoize_when_activated
def exe(self):
# Note: os.path.exists(path) may return False even if the file
# is there, see:
# http://stackoverflow.com/questions/3112546/os-path-exists-lies
# see https://github.com/giampaolo/psutil/issues/414
# see https://github.com/giampaolo/psutil/issues/528
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
return py2_strencode(convert_dos_path(cext.proc_exe(self.pid)))
if PYPY:
try:
exe = cext.proc_exe(self.pid)
except WindowsError as err:
# 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens
# (perhaps PyPy's JIT delaying garbage collection of files?).
if err.errno == 24:
debug("%r forced into AccessDenied" % err)
raise AccessDenied(self.pid, self._name)
raise
else:
exe = cext.proc_exe(self.pid)
if not PY3:
exe = py2_strencode(exe)
if exe.startswith('\\'):
return convert_dos_path(exe)
return exe # May be "Registry", "MemCompression", ...
@wrap_exceptions
@retry_error_partial_copy
def cmdline(self):
ret = cext.proc_cmdline(self.pid)
if cext.WINVER >= cext.WINDOWS_8_1:
# PEB method detects cmdline changes but requires more
# privileges: https://github.com/giampaolo/psutil/pull/1398
try:
ret = cext.proc_cmdline(self.pid, use_peb=True)
except OSError as err:
if is_permission_err(err):
ret = cext.proc_cmdline(self.pid, use_peb=False)
else:
raise
else:
ret = cext.proc_cmdline(self.pid, use_peb=True)
if PY3:
return ret
else:
return [py2_strencode(s) for s in ret]
@wrap_exceptions
@retry_error_partial_copy
def environ(self):
ustr = cext.proc_environ(self.pid)
if ustr and not PY3:
@ -725,10 +808,10 @@ class Process(object):
try:
return cext.proc_memory_info(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
if is_permission_err(err):
# TODO: the C ext can probably be refactored in order
# to get this from cext.proc_info()
info = self.oneshot_info()
info = self._proc_info()
return (
info[pinfo_map['num_page_faults']],
info[pinfo_map['peak_wset']],
@ -757,6 +840,7 @@ class Process(object):
def memory_full_info(self):
basic_mem = self.memory_info()
uss = cext.proc_memory_uss(self.pid)
uss *= getpagesize()
return pfullmem(*basic_mem + (uss, ))
def memory_maps(self):
@ -765,16 +849,11 @@ class Process(object):
except OSError as err:
# XXX - can't use wrap_exceptions decorator as we're
# returning a generator; probably needs refactoring.
if err.errno in ACCESS_DENIED_ERRSET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
raise
raise convert_oserror(err, self.pid, self._name)
else:
for addr, perm, path, rss in raw:
path = convert_dos_path(path)
if not PY3:
assert isinstance(path, unicode), type(path)
path = py2_strencode(path)
addr = hex(addr)
yield (addr, perm, path, rss)
@ -785,25 +864,59 @@ class Process(object):
@wrap_exceptions
def send_signal(self, sig):
os.kill(self.pid, sig)
if sig == signal.SIGTERM:
cext.proc_kill(self.pid)
# py >= 2.7
elif sig in (getattr(signal, "CTRL_C_EVENT", object()),
getattr(signal, "CTRL_BREAK_EVENT", object())):
os.kill(self.pid, sig)
else:
raise ValueError(
"only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
"are supported on Windows")
@wrap_exceptions
def wait(self, timeout=None):
if timeout is None:
cext_timeout = cext.INFINITE
else:
# WaitForSingleObject() expects time in milliseconds
# WaitForSingleObject() expects time in milliseconds.
cext_timeout = int(timeout * 1000)
timer = getattr(time, 'monotonic', time.time)
stop_at = timer() + timeout if timeout is not None else None
try:
# Exit code is supposed to come from GetExitCodeProcess().
# May also be None if OpenProcess() failed with
# ERROR_INVALID_PARAMETER, meaning PID is already gone.
exit_code = cext.proc_wait(self.pid, cext_timeout)
except cext.TimeoutExpired:
# WaitForSingleObject() returned WAIT_TIMEOUT. Just raise.
raise TimeoutExpired(timeout, self.pid, self._name)
except cext.TimeoutAbandoned:
# WaitForSingleObject() returned WAIT_ABANDONED, see:
# https://github.com/giampaolo/psutil/issues/1224
# We'll just rely on the internal polling and return None
# when the PID disappears. Subprocess module does the same
# (return None):
# https://github.com/python/cpython/blob/
# be50a7b627d0aa37e08fa8e2d5568891f19903ce/
# Lib/subprocess.py#L1193-L1194
exit_code = None
# At this point WaitForSingleObject() returned WAIT_OBJECT_0,
# meaning the process is gone. Stupidly there are cases where
# its PID may still stick around so we do a further internal
# polling.
delay = 0.0001
while True:
ret = cext.proc_wait(self.pid, cext_timeout)
if ret == WAIT_TIMEOUT:
raise TimeoutExpired(timeout, self.pid, self._name)
if pid_exists(self.pid):
if timeout is None:
continue
else:
raise TimeoutExpired(timeout, self.pid, self._name)
return ret
if not pid_exists(self.pid):
return exit_code
if stop_at and timer() >= stop_at:
raise TimeoutExpired(timeout, pid=self.pid, name=self._name)
time.sleep(delay)
delay = min(delay * 2, 0.04) # incremental delay
@wrap_exceptions
def username(self):
@ -814,19 +927,19 @@ class Process(object):
@wrap_exceptions
def create_time(self):
# special case for kernel process PIDs; return system boot time
if self.pid in (0, 4):
return boot_time()
# Note: proc_times() not put under oneshot() 'cause create_time()
# is already cached by the main Process class.
try:
return cext.proc_create_time(self.pid)
user, system, created = cext.proc_times(self.pid)
return created
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
return self.oneshot_info()[pinfo_map['create_time']]
if is_permission_err(err):
return self._proc_info()[pinfo_map['create_time']]
raise
@wrap_exceptions
def num_threads(self):
return self.oneshot_info()[pinfo_map['num_threads']]
return self._proc_info()[pinfo_map['num_threads']]
@wrap_exceptions
def threads(self):
@ -840,26 +953,26 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
try:
user, system = cext.proc_cpu_times(self.pid)
user, system, created = cext.proc_times(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
info = self.oneshot_info()
user = info[pinfo_map['user_time']]
system = info[pinfo_map['kernel_time']]
else:
if not is_permission_err(err):
raise
info = self._proc_info()
user = info[pinfo_map['user_time']]
system = info[pinfo_map['kernel_time']]
# Children user/system times are not retrievable (set to 0).
return _common.pcputimes(user, system, 0.0, 0.0)
@wrap_exceptions
def suspend(self):
return cext.proc_suspend(self.pid)
cext.proc_suspend_or_resume(self.pid, True)
@wrap_exceptions
def resume(self):
return cext.proc_resume(self.pid)
cext.proc_suspend_or_resume(self.pid, False)
@wrap_exceptions
@retry_error_partial_copy
def cwd(self):
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
@ -902,39 +1015,38 @@ class Process(object):
def nice_set(self, value):
return cext.proc_priority_set(self.pid, value)
# available on Windows >= Vista
if hasattr(cext, "proc_io_priority_get"):
@wrap_exceptions
def ionice_get(self):
return cext.proc_io_priority_get(self.pid)
@wrap_exceptions
def ionice_get(self):
ret = cext.proc_io_priority_get(self.pid)
if enum is not None:
ret = IOPriority(ret)
return ret
@wrap_exceptions
def ionice_set(self, value, _):
if _:
raise TypeError("set_proc_ionice() on Windows takes only "
"1 argument (2 given)")
if value not in (2, 1, 0):
raise ValueError("value must be 2 (normal), 1 (low) or 0 "
"(very low); got %r" % value)
return cext.proc_io_priority_set(self.pid, value)
@wrap_exceptions
def ionice_set(self, ioclass, value):
if value:
raise TypeError("value argument not accepted on Windows")
if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL,
IOPRIO_HIGH):
raise ValueError("%s is not a valid priority" % ioclass)
cext.proc_io_priority_set(self.pid, ioclass)
@wrap_exceptions
def io_counters(self):
try:
ret = cext.proc_io_counters(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
info = self.oneshot_info()
ret = (
info[pinfo_map['io_rcount']],
info[pinfo_map['io_wcount']],
info[pinfo_map['io_rbytes']],
info[pinfo_map['io_wbytes']],
info[pinfo_map['io_count_others']],
info[pinfo_map['io_bytes_others']],
)
else:
if not is_permission_err(err):
raise
info = self._proc_info()
ret = (
info[pinfo_map['io_rcount']],
info[pinfo_map['io_wcount']],
info[pinfo_map['io_rbytes']],
info[pinfo_map['io_wbytes']],
info[pinfo_map['io_count_others']],
info[pinfo_map['io_bytes_others']],
)
return pio(*ret)
@wrap_exceptions
@ -982,12 +1094,12 @@ class Process(object):
try:
return cext.proc_num_handles(self.pid)
except OSError as err:
if err.errno in ACCESS_DENIED_ERRSET:
return self.oneshot_info()[pinfo_map['num_handles']]
if is_permission_err(err):
return self._proc_info()[pinfo_map['num_handles']]
raise
@wrap_exceptions
def num_ctx_switches(self):
ctx_switches = self.oneshot_info()[pinfo_map['ctx_switches']]
ctx_switches = self._proc_info()[pinfo_map['ctx_switches']]
# only voluntary ctx switches are supported
return _common.pctxsw(ctx_switches, 0)

Просмотреть файл

@ -32,15 +32,18 @@ import traceback
import warnings
from socket import AF_INET
from socket import AF_INET6
from socket import SOCK_DGRAM
from socket import SOCK_STREAM
import psutil
from psutil import OSX
from psutil import AIX
from psutil import MACOS
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import supports_ipv6
from psutil._compat import ChildProcessError
from psutil._compat import FileExistsError
from psutil._compat import FileNotFoundError
from psutil._compat import PY3
from psutil._compat import u
from psutil._compat import unicode
@ -54,7 +57,9 @@ else:
try:
from unittest import mock # py3
except ImportError:
import mock # NOQA - requires "pip install mock"
with warnings.catch_warnings():
warnings.simplefilter("ignore")
import mock # NOQA - requires "pip install mock"
if sys.version_info >= (3, 4):
import enum
@ -66,8 +71,8 @@ __all__ = [
# constants
'APPVEYOR', 'DEVNULL', 'GLOBAL_TIMEOUT', 'MEMORY_TOLERANCE', 'NO_RETRIES',
'PYPY', 'PYTHON_EXE', 'ROOT_DIR', 'SCRIPTS_DIR', 'TESTFILE_PREFIX',
'TESTFN', 'TESTFN_UNICODE', 'TOX', 'TRAVIS', 'VALID_PROC_STATUSES',
'VERBOSITY',
'TESTFN', 'TESTFN_UNICODE', 'TOX', 'TRAVIS', 'CIRRUS', 'CI_TESTING',
'VALID_PROC_STATUSES',
"HAS_CPU_AFFINITY", "HAS_CPU_FREQ", "HAS_ENVIRON", "HAS_PROC_IO_COUNTERS",
"HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT",
"HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS",
@ -79,8 +84,7 @@ __all__ = [
'ThreadTask'
# test utils
'unittest', 'skip_on_access_denied', 'skip_on_not_implemented',
'retry_before_failing', 'run_test_module_by_name', 'get_suite',
'run_suite',
'retry_on_failure',
# install utils
'install_pip', 'install_test_deps',
# fs utils
@ -91,7 +95,7 @@ __all__ = [
# sync primitives
'call_until', 'wait_for_pid', 'wait_for_file',
# network
'check_connection_ntuple', 'check_net_address',
'check_net_address',
'get_free_port', 'unix_socket_path', 'bind_socket', 'bind_unix_socket',
'tcp_socketpair', 'unix_socketpair', 'create_sockets',
# compat
@ -109,23 +113,20 @@ __all__ = [
TOX = os.getenv('TOX') or '' in ('1', 'true')
PYPY = '__pypy__' in sys.builtin_module_names
WIN_VISTA = (6, 0, 0) if WINDOWS else None
# whether we're running this test suite on Travis (https://travis-ci.org/)
# whether we're running this test suite on a Continuous Integration service
TRAVIS = bool(os.environ.get('TRAVIS'))
# whether we're running this test suite on Appveyor for Windows
# (http://www.appveyor.com/)
APPVEYOR = bool(os.environ.get('APPVEYOR'))
CIRRUS = bool(os.environ.get('CIRRUS'))
CI_TESTING = TRAVIS or APPVEYOR or CIRRUS
# --- configurable defaults
# how many times retry_before_failing() decorator will retry
# how many times retry_on_failure() decorator will retry
NO_RETRIES = 10
# bytes tolerance for system-wide memory related tests
MEMORY_TOLERANCE = 500 * 1024 # 500KB
# the timeout used in functions which have to wait
GLOBAL_TIMEOUT = 3
# test output verbosity
VERBOSITY = 1 if os.getenv('SILENT') or TOX else 2
GLOBAL_TIMEOUT = 5
# be more tolerant if we're on travis / appveyor in order to avoid
# false positives
if TRAVIS or APPVEYOR:
@ -135,34 +136,49 @@ if TRAVIS or APPVEYOR:
# --- files
TESTFILE_PREFIX = '$testfn'
if os.name == 'java':
# Jython disallows @ in module names
TESTFILE_PREFIX = '$psutil-test-'
else:
TESTFILE_PREFIX = '@psutil-test-'
TESTFN = os.path.join(os.path.realpath(os.getcwd()), TESTFILE_PREFIX)
# Disambiguate TESTFN for parallel testing, while letting it remain a valid
# module name.
TESTFN = TESTFN + str(os.getpid())
_TESTFN = TESTFN + '-internal'
TESTFN_UNICODE = TESTFN + u("-ƒőő")
ASCII_FS = sys.getfilesystemencoding().lower() in ('ascii', 'us-ascii')
# --- paths
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
ROOT_DIR = os.path.realpath(
os.path.join(os.path.dirname(__file__), '..', '..'))
SCRIPTS_DIR = os.path.join(ROOT_DIR, 'scripts')
HERE = os.path.abspath(os.path.dirname(__file__))
HERE = os.path.realpath(os.path.dirname(__file__))
# --- support
HAS_CONNECTIONS_UNIX = POSIX and not SUNOS
HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity")
HAS_CPU_FREQ = hasattr(psutil, "cpu_freq")
HAS_CONNECTIONS_UNIX = POSIX and not SUNOS
HAS_GETLOADAVG = hasattr(psutil, "getloadavg")
HAS_ENVIRON = hasattr(psutil.Process, "environ")
HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters")
HAS_IONICE = hasattr(psutil.Process, "ionice")
HAS_MEMORY_FULL_INFO = 'uss' in psutil.Process().memory_full_info()._fields
HAS_MEMORY_MAPS = hasattr(psutil.Process, "memory_maps")
HAS_NET_IO_COUNTERS = hasattr(psutil, "net_io_counters")
HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num")
HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters")
HAS_RLIMIT = hasattr(psutil.Process, "rlimit")
HAS_THREADS = hasattr(psutil.Process, "threads")
HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery")
HAS_BATTERY = HAS_SENSORS_BATTERY and psutil.sensors_battery()
try:
HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery())
except Exception:
HAS_BATTERY = True
HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans")
HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures")
HAS_THREADS = hasattr(psutil.Process, "threads")
SKIP_SYSCONS = (MACOS or AIX) and os.getuid() != 0
# --- misc
@ -177,7 +193,7 @@ def _get_py_exe():
else:
return exe
if OSX:
if MACOS:
exe = \
attempt(sys.executable) or \
attempt(os.path.realpath(sys.executable)) or \
@ -197,7 +213,6 @@ DEVNULL = open(os.devnull, 'r+')
VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil)
if x.startswith('STATUS_')]
AF_UNIX = getattr(socket, "AF_UNIX", object())
SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object())
_subprocesses_started = set()
_pids_started = set()
@ -205,7 +220,7 @@ _testfiles_created = set()
@atexit.register
def _cleanup_files():
def cleanup_test_files():
DEVNULL.close()
for name in os.listdir(u('.')):
if isinstance(name, unicode):
@ -226,7 +241,7 @@ def _cleanup_files():
# this is executed first
@atexit.register
def _cleanup_procs():
def cleanup_test_procs():
reap_children(recursive=True)
@ -283,7 +298,7 @@ class ThreadTask(threading.Thread):
# ===================================================================
def _cleanup_on_err(fun):
def _reap_children_on_err(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
try:
@ -294,7 +309,7 @@ def _cleanup_on_err(fun):
return wrapper
@_cleanup_on_err
@_reap_children_on_err
def get_test_subprocess(cmd=None, **kwds):
"""Creates a python subprocess which does nothing for 60 secs and
return it as subprocess.Popen instance.
@ -309,8 +324,11 @@ def get_test_subprocess(cmd=None, **kwds):
kwds.setdefault("cwd", os.getcwd())
kwds.setdefault("env", os.environ)
if WINDOWS:
# Prevents the subprocess to open error dialogs.
kwds.setdefault("creationflags", 0x8000000) # CREATE_NO_WINDOW
# Prevents the subprocess to open error dialogs. This will also
# cause stderr to be suppressed, which is suboptimal in order
# to debug broken tests.
CREATE_NO_WINDOW = 0x8000000
kwds.setdefault("creationflags", CREATE_NO_WINDOW)
if cmd is None:
safe_rmpath(_TESTFN)
pyline = "from time import sleep;" \
@ -327,7 +345,7 @@ def get_test_subprocess(cmd=None, **kwds):
return sproc
@_cleanup_on_err
@_reap_children_on_err
def create_proc_children_pair():
"""Create a subprocess which creates another one as in:
A (us) -> B (child) -> C (grandchild).
@ -343,8 +361,8 @@ def create_proc_children_pair():
s += "f.write(str(os.getpid()));"
s += "f.close();"
s += "time.sleep(60);"
subprocess.Popen(['%s', '-c', s])
time.sleep(60)
p = subprocess.Popen([r'%s', '-c', s])
p.wait()
""" % (_TESTFN2, PYTHON_EXE))
# On Windows if we create a subprocess with CREATE_NO_WINDOW flag
# set (which is the default) a "conhost.exe" extra process will be
@ -355,7 +373,7 @@ def create_proc_children_pair():
subp = pyrun(s)
child1 = psutil.Process(subp.pid)
data = wait_for_file(_TESTFN2, delete=False, empty=False)
os.remove(_TESTFN2)
safe_rmpath(_TESTFN2)
child2_pid = int(data)
_pids_started.add(child2_pid)
child2 = psutil.Process(child2_pid)
@ -365,7 +383,7 @@ def create_proc_children_pair():
def create_zombie_proc():
"""Create a zombie process and return its PID."""
assert psutil.POSIX
unix_file = tempfile.mktemp(prefix=TESTFILE_PREFIX) if OSX else TESTFN
unix_file = tempfile.mktemp(prefix=TESTFILE_PREFIX) if MACOS else TESTFN
src = textwrap.dedent("""\
import os, sys, time, socket, contextlib
child_pid = os.fork()
@ -385,7 +403,7 @@ def create_zombie_proc():
with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock:
sock.settimeout(GLOBAL_TIMEOUT)
sock.bind(unix_file)
sock.listen(1)
sock.listen(5)
pyrun(src)
conn, _ = sock.accept()
try:
@ -399,7 +417,7 @@ def create_zombie_proc():
conn.close()
@_cleanup_on_err
@_reap_children_on_err
def pyrun(src, **kwds):
"""Run python 'src' code string in a separate interpreter.
Returns a subprocess.Popen instance.
@ -416,7 +434,7 @@ def pyrun(src, **kwds):
return subp
@_cleanup_on_err
@_reap_children_on_err
def sh(cmd, **kwds):
"""run cmd in a subprocess and return its output.
raises RuntimeError on error.
@ -431,7 +449,10 @@ def sh(cmd, **kwds):
kwds.setdefault("creationflags", flags)
p = subprocess.Popen(cmd, **kwds)
_subprocesses_started.add(p)
stdout, stderr = p.communicate()
if PY3:
stdout, stderr = p.communicate(timeout=GLOBAL_TIMEOUT)
else:
stdout, stderr = p.communicate()
if p.returncode != 0:
raise RuntimeError(stderr)
if stderr:
@ -480,7 +501,9 @@ def reap_children(recursive=False):
try:
subp.terminate()
except OSError as err:
if err.errno != errno.ESRCH:
if WINDOWS and err.winerror == 6: # "invalid handle"
pass
elif err.errno != errno.ESRCH:
raise
if subp.stdout:
subp.stdout.close()
@ -494,9 +517,8 @@ def reap_children(recursive=False):
# Wait for the process to terminate, to avoid zombies.
try:
subp.wait()
except OSError as err:
if err.errno != errno.ECHILD:
raise
except ChildProcessError:
pass
# Terminate started pids.
while _pids_started:
@ -588,7 +610,7 @@ class retry(object):
timeout=None,
retries=None,
interval=0.001,
logfun=lambda s: print(s, file=sys.stderr),
logfun=None,
):
if timeout and retries:
raise ValueError("timeout and retries args are mutually exclusive")
@ -621,7 +643,7 @@ class retry(object):
for _ in self:
try:
return fun(*args, **kwargs)
except self.exception as _:
except self.exception as _: # NOQA
exc = _
if self.logfun is not None:
self.logfun(exc)
@ -659,7 +681,7 @@ def wait_for_file(fname, delete=True, empty=False):
if not empty:
assert data
if delete:
os.remove(fname)
safe_rmpath(fname)
return data
@ -681,24 +703,43 @@ def call_until(fun, expr):
def safe_rmpath(path):
"Convenience function for removing temporary test files or dirs"
def retry_fun(fun):
# On Windows it could happen that the file or directory has
# open handles or references preventing the delete operation
# to succeed immediately, so we retry for a while. See:
# https://bugs.python.org/issue33240
stop_at = time.time() + 1
while time.time() < stop_at:
try:
return fun()
except FileNotFoundError:
pass
except WindowsError as _:
err = _
warn("ignoring %s" % (str(err)))
time.sleep(0.01)
raise err
try:
st = os.stat(path)
if stat.S_ISDIR(st.st_mode):
os.rmdir(path)
fun = functools.partial(shutil.rmtree, path)
else:
os.remove(path)
except OSError as err:
if err.errno != errno.ENOENT:
raise
fun = functools.partial(os.remove, path)
if POSIX:
fun()
else:
retry_fun(fun)
except FileNotFoundError:
pass
def safe_mkdir(dir):
"Convenience function for creating a directory"
try:
os.mkdir(dir)
except OSError as err:
if err.errno != errno.EEXIST:
raise
except FileExistsError:
pass
@contextlib.contextmanager
@ -757,9 +798,11 @@ class TestCase(unittest.TestCase):
# Print a full path representation of the single unit tests
# being run.
def __str__(self):
fqmod = self.__class__.__module__
if not fqmod.startswith('psutil.'):
fqmod = 'psutil.tests.' + fqmod
return "%s.%s.%s" % (
self.__class__.__module__, self.__class__.__name__,
self._testMethodName)
fqmod, self.__class__.__name__, self._testMethodName)
# assertRaisesRegexp renamed to assertRaisesRegex in 3.3;
# add support for the new name.
@ -771,52 +814,15 @@ class TestCase(unittest.TestCase):
unittest.TestCase = TestCase
def _setup_tests():
if 'PSUTIL_TESTING' not in os.environ:
# This won't work on Windows but set_testing() below will do it.
os.environ['PSUTIL_TESTING'] = '1'
psutil._psplatform.cext.set_testing()
def get_suite():
testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE)
if x.endswith('.py') and x.startswith('test_') and not
x.startswith('test_memory_leaks')]
if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ:
testmods = [x for x in testmods if not x.endswith((
"osx", "posix", "linux"))]
suite = unittest.TestSuite()
for tm in testmods:
# ...so that the full test paths are printed on screen
tm = "psutil.tests.%s" % tm
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm))
return suite
def run_suite():
_setup_tests()
result = unittest.TextTestRunner(verbosity=VERBOSITY).run(get_suite())
success = result.wasSuccessful()
sys.exit(0 if success else 1)
def run_test_module_by_name(name):
# testmodules = [os.path.splitext(x)[0] for x in os.listdir(HERE)
# if x.endswith('.py') and x.startswith('test_')]
_setup_tests()
name = os.path.splitext(os.path.basename(name))[0]
suite = unittest.TestSuite()
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name))
result = unittest.TextTestRunner(verbosity=VERBOSITY).run(suite)
success = result.wasSuccessful()
sys.exit(0 if success else 1)
def retry_before_failing(retries=NO_RETRIES):
def retry_on_failure(retries=NO_RETRIES):
"""Decorator which runs a test function and retries N times before
actually failing.
"""
return retry(exception=AssertionError, timeout=None, retries=retries)
def logfun(exc):
print("%r, retrying" % exc, file=sys.stderr)
return retry(exception=AssertionError, timeout=None, retries=retries,
logfun=logfun)
def skip_on_access_denied(only_if=None):
@ -861,7 +867,6 @@ def skip_on_not_implemented(only_if=None):
def get_free_port(host='127.0.0.1'):
"""Return an unused TCP port."""
with contextlib.closing(socket.socket()) as sock:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((host, 0))
return sock.getsockname()[1]
@ -888,10 +893,11 @@ def bind_socket(family=AF_INET, type=SOCK_STREAM, addr=None):
addr = ("", 0)
sock = socket.socket(family, type)
try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if os.name not in ('nt', 'cygwin'):
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
if type == socket.SOCK_STREAM:
sock.listen(10)
sock.listen(5)
return sock
except Exception:
sock.close()
@ -906,7 +912,7 @@ def bind_unix_socket(name, type=socket.SOCK_STREAM):
try:
sock.bind(name)
if type == socket.SOCK_STREAM:
sock.listen(10)
sock.listen(5)
except Exception:
sock.close()
raise
@ -919,7 +925,7 @@ def tcp_socketpair(family, addr=("", 0)):
"""
with contextlib.closing(socket.socket(family, SOCK_STREAM)) as ll:
ll.bind(addr)
ll.listen(10)
ll.listen(5)
addr = ll.getsockname()
c = socket.socket(family, SOCK_STREAM)
try:
@ -1015,77 +1021,6 @@ def check_net_address(addr, family):
raise ValueError("unknown family %r", family)
def check_connection_ntuple(conn):
"""Check validity of a connection namedtuple."""
# check ntuple
assert len(conn) in (6, 7), conn
has_pid = len(conn) == 7
has_fd = getattr(conn, 'fd', -1) != -1
assert conn[0] == conn.fd
assert conn[1] == conn.family
assert conn[2] == conn.type
assert conn[3] == conn.laddr
assert conn[4] == conn.raddr
assert conn[5] == conn.status
if has_pid:
assert conn[6] == conn.pid
# check fd
if has_fd:
assert conn.fd >= 0, conn
if hasattr(socket, 'fromfd') and not WINDOWS:
try:
dupsock = socket.fromfd(conn.fd, conn.family, conn.type)
except (socket.error, OSError) as err:
if err.args[0] != errno.EBADF:
raise
else:
with contextlib.closing(dupsock):
assert dupsock.family == conn.family
assert dupsock.type == conn.type
# check family
assert conn.family in (AF_INET, AF_INET6, AF_UNIX), repr(conn.family)
if conn.family in (AF_INET, AF_INET6):
# actually try to bind the local socket; ignore IPv6
# sockets as their address might be represented as
# an IPv4-mapped-address (e.g. "::127.0.0.1")
# and that's rejected by bind()
if conn.family == AF_INET:
s = socket.socket(conn.family, conn.type)
with contextlib.closing(s):
try:
s.bind((conn.laddr[0], 0))
except socket.error as err:
if err.errno != errno.EADDRNOTAVAIL:
raise
elif conn.family == AF_UNIX:
assert conn.status == psutil.CONN_NONE, conn.status
# check type (SOCK_SEQPACKET may happen in case of AF_UNIX socks)
assert conn.type in (SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET), \
repr(conn.type)
if conn.type == SOCK_DGRAM:
assert conn.status == psutil.CONN_NONE, conn.status
# check laddr (IP address and port sanity)
for addr in (conn.laddr, conn.raddr):
if conn.family in (AF_INET, AF_INET6):
assert isinstance(addr, tuple), addr
if not addr:
continue
assert isinstance(addr.port, int), addr.port
assert 0 <= addr.port <= 65535, addr.port
check_net_address(addr.ip, conn.family)
elif conn.family == AF_UNIX:
assert isinstance(addr, str), addr
# check status
assert isinstance(conn.status, str), conn
valids = [getattr(psutil, x) for x in dir(psutil) if x.startswith('CONN_')]
assert conn.status in valids, conn
# ===================================================================
# --- compatibility
# ===================================================================
@ -1149,11 +1084,12 @@ if POSIX:
by this process, copies it in another location and loads it
in memory via ctypes. Return the new absolutized path.
"""
exe = 'pypy' if PYPY else 'python'
ext = ".so"
dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext)
libs = [x.path for x in psutil.Process().memory_maps() if
os.path.splitext(x.path)[1] == ext and
'python' in x.path.lower()]
exe in x.path.lower()]
src = random.choice(libs)
shutil.copyfile(src, dst)
try:
@ -1174,9 +1110,12 @@ else:
ext = ".dll"
dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext)
libs = [x.path for x in psutil.Process().memory_maps() if
os.path.splitext(x.path)[1].lower() == ext and
x.path.lower().endswith(ext) and
'python' in os.path.basename(x.path).lower() and
'wow64' not in x.path.lower()]
if PYPY and not libs:
libs = [x.path for x in psutil.Process().memory_maps() if
'pypy' in os.path.basename(x.path).lower()]
src = random.choice(libs)
shutil.copyfile(src, dst)
cfile = None

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -6,91 +6,8 @@
"""
Run unit tests. This is invoked by:
$ python -m psutil.tests
"""
import contextlib
import optparse
import os
import ssl
import sys
import tempfile
try:
from urllib.request import urlopen # py3
except ImportError:
from urllib2 import urlopen
from psutil.tests import PYTHON_EXE
from psutil.tests import run_suite
HERE = os.path.abspath(os.path.dirname(__file__))
GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
TEST_DEPS = []
if sys.version_info[:2] == (2, 6):
TEST_DEPS.extend(["ipaddress", "unittest2", "argparse", "mock==1.0.1"])
elif sys.version_info[:2] == (2, 7) or sys.version_info[:2] <= (3, 2):
TEST_DEPS.extend(["ipaddress", "mock"])
elif sys.version_info[:2] == (3, 3):
TEST_DEPS.extend(["ipaddress"])
def install_pip():
try:
import pip # NOQA
except ImportError:
f = tempfile.NamedTemporaryFile(suffix='.py')
with contextlib.closing(f):
print("downloading %s to %s" % (GET_PIP_URL, f.name))
if hasattr(ssl, '_create_unverified_context'):
ctx = ssl._create_unverified_context()
else:
ctx = None
kwargs = dict(context=ctx) if ctx else {}
req = urlopen(GET_PIP_URL, **kwargs)
data = req.read()
f.write(data)
f.flush()
print("installing pip")
code = os.system('%s %s --user' % (PYTHON_EXE, f.name))
return code
def install_test_deps(deps=None):
"""Install test dependencies via pip."""
if deps is None:
deps = TEST_DEPS
deps = set(deps)
if deps:
is_venv = hasattr(sys, 'real_prefix')
opts = "--user" if not is_venv else ""
install_pip()
code = os.system('%s -m pip install %s --upgrade %s' % (
PYTHON_EXE, opts, " ".join(deps)))
return code
def main():
usage = "%s -m psutil.tests [opts]" % PYTHON_EXE
parser = optparse.OptionParser(usage=usage, description="run unit tests")
parser.add_option("-i", "--install-deps",
action="store_true", default=False,
help="don't print status messages to stdout")
opts, args = parser.parse_args()
if opts.install_deps:
install_pip()
install_test_deps()
else:
for dep in TEST_DEPS:
try:
__import__(dep.split("==")[0])
except ImportError:
sys.exit("%r lib is not installed; run %s -m psutil.tests "
"--install-deps" % (dep, PYTHON_EXE))
run_suite()
from .runner import main
main()

Просмотреть файл

@ -0,0 +1,162 @@
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Unit test runner, providing new features on top of unittest module:
- colourized output (error, skip)
- print failures/tracebacks on CTRL+C
- re-run failed tests only (make test-failed)
"""
from __future__ import print_function
import optparse
import os
import sys
import unittest
from unittest import TestResult
from unittest import TextTestResult
from unittest import TextTestRunner
try:
import ctypes
except ImportError:
ctypes = None
import psutil
from psutil._common import hilite
from psutil._common import print_color
from psutil._common import term_supports_colors
from psutil.tests import safe_rmpath
from psutil.tests import TOX
HERE = os.path.abspath(os.path.dirname(__file__))
VERBOSITY = 1 if TOX else 2
FAILED_TESTS_FNAME = '.failed-tests.txt'
# =====================================================================
# --- unittest subclasses
# =====================================================================
class ColouredResult(TextTestResult):
def _print_color(self, s, color, bold=False):
file = sys.stderr if color == "red" else sys.stdout
print_color(s, color, bold=bold, file=file)
def addSuccess(self, test):
TestResult.addSuccess(self, test)
self._print_color("OK", "green")
def addError(self, test, err):
TestResult.addError(self, test, err)
self._print_color("ERROR", "red", bold=True)
def addFailure(self, test, err):
TestResult.addFailure(self, test, err)
self._print_color("FAIL", "red")
def addSkip(self, test, reason):
TestResult.addSkip(self, test, reason)
self._print_color("skipped: %s" % reason, "brown")
def printErrorList(self, flavour, errors):
flavour = hilite(flavour, "red", bold=flavour == 'ERROR')
TextTestResult.printErrorList(self, flavour, errors)
class ColouredRunner(TextTestRunner):
resultclass = ColouredResult if term_supports_colors() else TextTestResult
def _makeResult(self):
# Store result instance so that it can be accessed on
# KeyboardInterrupt.
self.result = TextTestRunner._makeResult(self)
return self.result
# =====================================================================
# --- public API
# =====================================================================
def setup_tests():
if 'PSUTIL_TESTING' not in os.environ:
# This won't work on Windows but set_testing() below will do it.
os.environ['PSUTIL_TESTING'] = '1'
psutil._psplatform.cext.set_testing()
def get_suite(name=None):
suite = unittest.TestSuite()
if name is None:
testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE)
if x.endswith('.py') and x.startswith('test_') and not
x.startswith('test_memory_leaks')]
if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ:
testmods = [x for x in testmods if not x.endswith((
"osx", "posix", "linux"))]
for tm in testmods:
# ...so that the full test paths are printed on screen
tm = "psutil.tests.%s" % tm
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm))
else:
name = os.path.splitext(os.path.basename(name))[0]
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name))
return suite
def get_suite_from_failed():
# ...from previously failed test run
suite = unittest.TestSuite()
if not os.path.isfile(FAILED_TESTS_FNAME):
return suite
with open(FAILED_TESTS_FNAME, 'rt') as f:
names = f.read().split()
for n in names:
suite.addTest(unittest.defaultTestLoader.loadTestsFromName(n))
return suite
def save_failed_tests(result):
if result.wasSuccessful():
return safe_rmpath(FAILED_TESTS_FNAME)
with open(FAILED_TESTS_FNAME, 'wt') as f:
for t in result.errors + result.failures:
tname = str(t[0])
unittest.defaultTestLoader.loadTestsFromName(tname)
f.write(tname + '\n')
def run(name=None, last_failed=False):
setup_tests()
runner = ColouredRunner(verbosity=VERBOSITY)
suite = get_suite_from_failed() if last_failed else get_suite(name)
try:
result = runner.run(suite)
except (KeyboardInterrupt, SystemExit) as err:
print("received %s" % err.__class__.__name__, file=sys.stderr)
runner.result.printErrors()
sys.exit(1)
else:
save_failed_tests(result)
success = result.wasSuccessful()
sys.exit(0 if success else 1)
def main():
usage = "python3 -m psutil.tests [opts]"
parser = optparse.OptionParser(usage=usage, description="run unit tests")
parser.add_option("--last-failed",
action="store_true", default=False,
help="only run last failed tests")
opts, args = parser.parse_args()
run(last_failed=opts.last_failed)
if __name__ == '__main__':
main()

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'
# Copyright (c) 2017, Arnon Yaari
@ -11,7 +11,6 @@
import re
from psutil import AIX
from psutil.tests import run_test_module_by_name
from psutil.tests import sh
from psutil.tests import unittest
import psutil
@ -22,9 +21,9 @@ class AIXSpecificTestCase(unittest.TestCase):
def test_virtual_memory(self):
out = sh('/usr/bin/svmon -O unit=KB')
re_pattern = "memory\s*"
re_pattern = r"memory\s*"
for field in ("size inuse free pin virtual available mmode").split():
re_pattern += "(?P<%s>\S+)\s+" % (field,)
re_pattern += r"(?P<%s>\S+)\s+" % (field,)
matchobj = re.search(re_pattern, out)
self.assertIsNotNone(
@ -56,10 +55,10 @@ class AIXSpecificTestCase(unittest.TestCase):
# we'll always have 'MB' in the result
# TODO maybe try to use "swap -l" to check "used" too, but its units
# are not guaranteed to be "MB" so parsing may not be consistent
matchobj = re.search("(?P<space>\S+)\s+"
"(?P<vol>\S+)\s+"
"(?P<vg>\S+)\s+"
"(?P<size>\d+)MB", out)
matchobj = re.search(r"(?P<space>\S+)\s+"
r"(?P<vol>\S+)\s+"
r"(?P<vg>\S+)\s+"
r"(?P<size>\d+)MB", out)
self.assertIsNotNone(
matchobj, "lsps command returned unexpected output")
@ -74,11 +73,11 @@ class AIXSpecificTestCase(unittest.TestCase):
def test_cpu_stats(self):
out = sh('/usr/bin/mpstat -a')
re_pattern = "ALL\s*"
re_pattern = r"ALL\s*"
for field in ("min maj mpcs mpcr dev soft dec ph cs ics bound rq "
"push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd "
"sysc").split():
re_pattern += "(?P<%s>\S+)\s+" % (field,)
re_pattern += r"(?P<%s>\S+)\s+" % (field,)
matchobj = re.search(re_pattern, out)
self.assertIsNotNone(
@ -106,7 +105,7 @@ class AIXSpecificTestCase(unittest.TestCase):
def test_cpu_count_logical(self):
out = sh('/usr/bin/mpstat -a')
mpstat_lcpu = int(re.search("lcpu=(\d+)", out).group(1))
mpstat_lcpu = int(re.search(r"lcpu=(\d+)", out).group(1))
psutil_lcpu = psutil.cpu_count(logical=True)
self.assertEqual(mpstat_lcpu, psutil_lcpu)
@ -118,4 +117,5 @@ class AIXSpecificTestCase(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -24,8 +24,7 @@ from psutil.tests import get_test_subprocess
from psutil.tests import HAS_BATTERY
from psutil.tests import MEMORY_TOLERANCE
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import unittest
from psutil.tests import which
@ -73,7 +72,7 @@ def muse(field):
@unittest.skipIf(not BSD, "BSD only")
class BSDSpecificTestCase(unittest.TestCase):
class BSDTestCase(unittest.TestCase):
"""Generic tests common to all BSD variants."""
@classmethod
@ -149,7 +148,7 @@ class BSDSpecificTestCase(unittest.TestCase):
@unittest.skipIf(not FREEBSD, "FREEBSD only")
class FreeBSDSpecificTestCase(unittest.TestCase):
class FreeBSDProcessTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
@ -159,8 +158,8 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
def tearDownClass(cls):
reap_children()
@retry_before_failing()
def test_proc_memory_maps(self):
@retry_on_failure()
def test_memory_maps(self):
out = sh('procstat -v %s' % self.pid)
maps = psutil.Process(self.pid).memory_maps(grouped=False)
lines = out.split('\n')[1:]
@ -174,17 +173,17 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
if not map.path.startswith('['):
self.assertEqual(fields[10], map.path)
def test_proc_exe(self):
def test_exe(self):
out = sh('procstat -b %s' % self.pid)
self.assertEqual(psutil.Process(self.pid).exe(),
out.split('\n')[1].split()[-1])
def test_proc_cmdline(self):
def test_cmdline(self):
out = sh('procstat -c %s' % self.pid)
self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()),
' '.join(out.split('\n')[1].split()[2:]))
def test_proc_uids_gids(self):
def test_uids_gids(self):
out = sh('procstat -s %s' % self.pid)
euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8]
p = psutil.Process(self.pid)
@ -197,8 +196,8 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
self.assertEqual(gids.effective, int(egid))
self.assertEqual(gids.saved, int(sgid))
@retry_before_failing()
def test_proc_ctx_switches(self):
@retry_on_failure()
def test_ctx_switches(self):
tested = []
out = sh('procstat -r %s' % self.pid)
p = psutil.Process(self.pid)
@ -217,8 +216,8 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
if len(tested) != 2:
raise RuntimeError("couldn't find lines match in procstat out")
@retry_before_failing()
def test_proc_cpu_times(self):
@retry_on_failure()
def test_cpu_times(self):
tested = []
out = sh('procstat -r %s' % self.pid)
p = psutil.Process(self.pid)
@ -237,39 +236,76 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
if len(tested) != 2:
raise RuntimeError("couldn't find lines match in procstat out")
@unittest.skipIf(not FREEBSD, "FREEBSD only")
class FreeBSDSystemTestCase(unittest.TestCase):
@staticmethod
def parse_swapinfo():
# the last line is always the total
output = sh("swapinfo -k").splitlines()[-1]
parts = re.split(r'\s+', output)
if not parts:
raise ValueError("Can't parse swapinfo: %s" % output)
# the size is in 1k units, so multiply by 1024
total, used, free = (int(p) * 1024 for p in parts[1:4])
return total, used, free
def test_cpu_frequency_against_sysctl(self):
# Currently only cpu 0 is frequency is supported in FreeBSD
# All other cores use the same frequency.
sensor = "dev.cpu.0.freq"
try:
sysctl_result = int(sysctl(sensor))
except RuntimeError:
self.skipTest("frequencies not supported by kernel")
self.assertEqual(psutil.cpu_freq().current, sysctl_result)
sensor = "dev.cpu.0.freq_levels"
sysctl_result = sysctl(sensor)
# sysctl returns a string of the format:
# <freq_level_1>/<voltage_level_1> <freq_level_2>/<voltage_level_2>...
# Ordered highest available to lowest available.
max_freq = int(sysctl_result.split()[0].split("/")[0])
min_freq = int(sysctl_result.split()[-1].split("/")[0])
self.assertEqual(psutil.cpu_freq().max, max_freq)
self.assertEqual(psutil.cpu_freq().min, min_freq)
# --- virtual_memory(); tests against sysctl
@retry_before_failing()
@retry_on_failure()
def test_vmem_active(self):
syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE
self.assertAlmostEqual(psutil.virtual_memory().active, syst,
delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_inactive(self):
syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE
self.assertAlmostEqual(psutil.virtual_memory().inactive, syst,
delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_wired(self):
syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE
self.assertAlmostEqual(psutil.virtual_memory().wired, syst,
delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_cached(self):
syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE
self.assertAlmostEqual(psutil.virtual_memory().cached, syst,
delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_free(self):
syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE
self.assertAlmostEqual(psutil.virtual_memory().free, syst,
delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_buffers(self):
syst = sysctl("vfs.bufspace")
self.assertAlmostEqual(psutil.virtual_memory().buffers, syst,
@ -283,42 +319,42 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
self.assertEqual(psutil.virtual_memory().total, num)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_active(self):
num = muse('Active')
self.assertAlmostEqual(psutil.virtual_memory().active, num,
delta=MEMORY_TOLERANCE)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_inactive(self):
num = muse('Inactive')
self.assertAlmostEqual(psutil.virtual_memory().inactive, num,
delta=MEMORY_TOLERANCE)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_wired(self):
num = muse('Wired')
self.assertAlmostEqual(psutil.virtual_memory().wired, num,
delta=MEMORY_TOLERANCE)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_cached(self):
num = muse('Cache')
self.assertAlmostEqual(psutil.virtual_memory().cached, num,
delta=MEMORY_TOLERANCE)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_free(self):
num = muse('Free')
self.assertAlmostEqual(psutil.virtual_memory().free, num,
delta=MEMORY_TOLERANCE)
@unittest.skipIf(not MUSE_AVAILABLE, "muse not installed")
@retry_before_failing()
@retry_on_failure()
def test_muse_vmem_buffers(self):
num = muse('Buffer')
self.assertAlmostEqual(psutil.virtual_memory().buffers, num,
@ -336,14 +372,33 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
self.assertAlmostEqual(psutil.cpu_stats().soft_interrupts,
sysctl('vm.stats.sys.v_soft'), delta=1000)
@retry_on_failure()
def test_cpu_stats_syscalls(self):
# pretty high tolerance but it looks like it's OK.
self.assertAlmostEqual(psutil.cpu_stats().syscalls,
sysctl('vm.stats.sys.v_syscall'), delta=1000)
sysctl('vm.stats.sys.v_syscall'), delta=200000)
# def test_cpu_stats_traps(self):
# self.assertAlmostEqual(psutil.cpu_stats().traps,
# sysctl('vm.stats.sys.v_trap'), delta=1000)
# --- swap memory
def test_swapmem_free(self):
total, used, free = self.parse_swapinfo()
self.assertAlmostEqual(
psutil.swap_memory().free, free, delta=MEMORY_TOLERANCE)
def test_swapmem_used(self):
total, used, free = self.parse_swapinfo()
self.assertAlmostEqual(
psutil.swap_memory().used, used, delta=MEMORY_TOLERANCE)
def test_swapmem_total(self):
total, used, free = self.parse_swapinfo()
self.assertAlmostEqual(
psutil.swap_memory().total, total, delta=MEMORY_TOLERANCE)
# --- others
def test_boot_time(self):
@ -397,6 +452,26 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
sysctl("hw.acpi.acline")
self.assertIsNone(psutil.sensors_battery())
# --- sensors_temperatures
def test_sensors_temperatures_against_sysctl(self):
num_cpus = psutil.cpu_count(True)
for cpu in range(num_cpus):
sensor = "dev.cpu.%s.temperature" % cpu
# sysctl returns a string in the format 46.0C
try:
sysctl_result = int(float(sysctl(sensor)[:-1]))
except RuntimeError:
self.skipTest("temperatures not supported by kernel")
self.assertAlmostEqual(
psutil.sensors_temperatures()["coretemp"][cpu].current,
sysctl_result, delta=10)
sensor = "dev.cpu.%s.coretemp.tjmax" % cpu
sysctl_result = int(float(sysctl(sensor)[:-1]))
self.assertEqual(
psutil.sensors_temperatures()["coretemp"][cpu].high,
sysctl_result)
# =====================================================================
# --- OpenBSD
@ -404,7 +479,7 @@ class FreeBSDSpecificTestCase(unittest.TestCase):
@unittest.skipIf(not OPENBSD, "OPENBSD only")
class OpenBSDSpecificTestCase(unittest.TestCase):
class OpenBSDTestCase(unittest.TestCase):
def test_boot_time(self):
s = sysctl('kern.boottime')
@ -419,11 +494,11 @@ class OpenBSDSpecificTestCase(unittest.TestCase):
@unittest.skipIf(not NETBSD, "NETBSD only")
class NetBSDSpecificTestCase(unittest.TestCase):
class NetBSDTestCase(unittest.TestCase):
@staticmethod
def parse_meminfo(look_for):
with open('/proc/meminfo', 'rb') as f:
with open('/proc/meminfo', 'rt') as f:
for line in f:
if line.startswith(look_for):
return int(line.split()[1]) * 1024
@ -486,4 +561,5 @@ class NetBSDSpecificTestCase(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -6,6 +6,8 @@
"""Tests for net_connections() and Process.connections() APIs."""
import contextlib
import errno
import os
import socket
import textwrap
@ -18,9 +20,9 @@ from socket import SOCK_STREAM
import psutil
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
@ -29,15 +31,17 @@ from psutil._compat import PY3
from psutil.tests import AF_UNIX
from psutil.tests import bind_socket
from psutil.tests import bind_unix_socket
from psutil.tests import check_connection_ntuple
from psutil.tests import check_net_address
from psutil.tests import CIRRUS
from psutil.tests import create_sockets
from psutil.tests import enum
from psutil.tests import get_free_port
from psutil.tests import HAS_CONNECTIONS_UNIX
from psutil.tests import pyrun
from psutil.tests import reap_children
from psutil.tests import run_test_module_by_name
from psutil.tests import safe_rmpath
from psutil.tests import skip_on_access_denied
from psutil.tests import SKIP_SYSCONS
from psutil.tests import tcp_socketpair
from psutil.tests import TESTFN
from psutil.tests import TRAVIS
@ -48,29 +52,147 @@ from psutil.tests import wait_for_file
thisproc = psutil.Process()
SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object())
class Base(object):
def setUp(self):
if not NETBSD:
# NetBSD opens a UNIX socket to /var/log/run.
safe_rmpath(TESTFN)
if not (NETBSD or FREEBSD):
# process opens a UNIX socket to /var/log/run.
cons = thisproc.connections(kind='all')
assert not cons, cons
def tearDown(self):
safe_rmpath(TESTFN)
reap_children()
if not NETBSD:
if not (FREEBSD or NETBSD):
# Make sure we closed all resources.
# NetBSD opens a UNIX socket to /var/log/run.
cons = thisproc.connections(kind='all')
assert not cons, cons
def compare_procsys_connections(self, pid, proc_cons, kind='all'):
"""Given a process PID and its list of connections compare
those against system-wide connections retrieved via
psutil.net_connections.
"""
try:
sys_cons = psutil.net_connections(kind=kind)
except psutil.AccessDenied:
# On MACOS, system-wide connections are retrieved by iterating
# over all processes
if MACOS:
return
else:
raise
# Filter for this proc PID and exlucde PIDs from the tuple.
sys_cons = [c[:-1] for c in sys_cons if c.pid == pid]
sys_cons.sort()
proc_cons.sort()
self.assertEqual(proc_cons, sys_cons)
def check_connection_ntuple(self, conn):
"""Check validity of a connection namedtuple."""
def check_ntuple(conn):
has_pid = len(conn) == 7
self.assertIn(len(conn), (6, 7))
self.assertEqual(conn[0], conn.fd)
self.assertEqual(conn[1], conn.family)
self.assertEqual(conn[2], conn.type)
self.assertEqual(conn[3], conn.laddr)
self.assertEqual(conn[4], conn.raddr)
self.assertEqual(conn[5], conn.status)
if has_pid:
self.assertEqual(conn[6], conn.pid)
def check_family(conn):
self.assertIn(conn.family, (AF_INET, AF_INET6, AF_UNIX))
if enum is not None:
assert isinstance(conn.family, enum.IntEnum), conn
else:
assert isinstance(conn.family, int), conn
if conn.family == AF_INET:
# actually try to bind the local socket; ignore IPv6
# sockets as their address might be represented as
# an IPv4-mapped-address (e.g. "::127.0.0.1")
# and that's rejected by bind()
s = socket.socket(conn.family, conn.type)
with contextlib.closing(s):
try:
s.bind((conn.laddr[0], 0))
except socket.error as err:
if err.errno != errno.EADDRNOTAVAIL:
raise
elif conn.family == AF_UNIX:
self.assertEqual(conn.status, psutil.CONN_NONE)
def check_type(conn):
# SOCK_SEQPACKET may happen in case of AF_UNIX socks
self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET))
if enum is not None:
assert isinstance(conn.type, enum.IntEnum), conn
else:
assert isinstance(conn.type, int), conn
if conn.type == SOCK_DGRAM:
self.assertEqual(conn.status, psutil.CONN_NONE)
def check_addrs(conn):
# check IP address and port sanity
for addr in (conn.laddr, conn.raddr):
if conn.family in (AF_INET, AF_INET6):
self.assertIsInstance(addr, tuple)
if not addr:
continue
self.assertIsInstance(addr.port, int)
assert 0 <= addr.port <= 65535, addr.port
check_net_address(addr.ip, conn.family)
elif conn.family == AF_UNIX:
self.assertIsInstance(addr, str)
def check_status(conn):
self.assertIsInstance(conn.status, str)
valids = [getattr(psutil, x) for x in dir(psutil)
if x.startswith('CONN_')]
self.assertIn(conn.status, valids)
if conn.family in (AF_INET, AF_INET6) and conn.type == SOCK_STREAM:
self.assertNotEqual(conn.status, psutil.CONN_NONE)
else:
self.assertEqual(conn.status, psutil.CONN_NONE)
check_ntuple(conn)
check_family(conn)
check_type(conn)
check_addrs(conn)
check_status(conn)
class TestBase(Base, unittest.TestCase):
@unittest.skipIf(SKIP_SYSCONS, "requires root")
def test_system(self):
with create_sockets():
for conn in psutil.net_connections(kind='all'):
self.check_connection_ntuple(conn)
def test_process(self):
with create_sockets():
for conn in psutil.Process().connections(kind='all'):
self.check_connection_ntuple(conn)
def test_invalid_kind(self):
self.assertRaises(ValueError, thisproc.connections, kind='???')
self.assertRaises(ValueError, psutil.net_connections, kind='???')
class TestUnconnectedSockets(Base, unittest.TestCase):
"""Tests sockets which are open but not connected to anything."""
def get_conn_from_sock(self, sock):
cons = thisproc.connections(kind='all')
smap = dict([(c.fd, c) for c in cons])
if NETBSD:
if NETBSD or FREEBSD:
# NetBSD opens a UNIX socket to /var/log/run
# so there may be more connections.
return smap[sock.fileno()]
@ -80,14 +202,13 @@ class Base(object):
self.assertEqual(smap[sock.fileno()].fd, sock.fileno())
return cons[0]
def check_socket(self, sock, conn=None):
def check_socket(self, sock):
"""Given a socket, makes sure it matches the one obtained
via psutil. It assumes this process created one connection
only (the one supposed to be checked).
"""
if conn is None:
conn = self.get_conn_from_sock(sock)
check_connection_ntuple(conn)
conn = self.get_conn_from_sock(sock)
self.check_connection_ntuple(conn)
# fd, family, type
if conn.fd != -1:
@ -113,38 +234,9 @@ class Base(object):
# XXX Solaris can't retrieve system-wide UNIX sockets
if sock.family == AF_UNIX and HAS_CONNECTIONS_UNIX:
cons = thisproc.connections(kind='all')
self.compare_procsys_connections(os.getpid(), cons)
self.compare_procsys_connections(os.getpid(), cons, kind='all')
return conn
def compare_procsys_connections(self, pid, proc_cons, kind='all'):
"""Given a process PID and its list of connections compare
those against system-wide connections retrieved via
psutil.net_connections.
"""
try:
sys_cons = psutil.net_connections(kind=kind)
except psutil.AccessDenied:
# On OSX, system-wide connections are retrieved by iterating
# over all processes
if OSX:
return
else:
raise
# Filter for this proc PID and exlucde PIDs from the tuple.
sys_cons = [c[:-1] for c in sys_cons if c.pid == pid]
sys_cons.sort()
proc_cons.sort()
self.assertEqual(proc_cons, sys_cons)
# =====================================================================
# --- Test unconnected sockets
# =====================================================================
class TestUnconnectedSockets(Base, unittest.TestCase):
"""Tests sockets which are open but not connected to anything."""
def test_tcp_v4(self):
addr = ("127.0.0.1", get_free_port())
with closing(bind_socket(AF_INET, SOCK_STREAM, addr=addr)) as sock:
@ -192,12 +284,7 @@ class TestUnconnectedSockets(Base, unittest.TestCase):
self.assertEqual(conn.status, psutil.CONN_NONE)
# =====================================================================
# --- Test connected sockets
# =====================================================================
class TestConnectedSocketPairs(Base, unittest.TestCase):
class TestConnectedSocket(Base, unittest.TestCase):
"""Test socket pairs which are are actually connected to
each other.
"""
@ -232,11 +319,14 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
cons = thisproc.connections(kind='unix')
assert not (cons[0].laddr and cons[0].raddr)
assert not (cons[1].laddr and cons[1].raddr)
if NETBSD:
if NETBSD or FREEBSD:
# On NetBSD creating a UNIX socket will cause
# a UNIX connection to /var/run/log.
cons = [c for c in cons if c.raddr != '/var/run/log']
self.assertEqual(len(cons), 2)
if CIRRUS:
cons = [c for c in cons if c.fd in
(server.fileno(), client.fileno())]
self.assertEqual(len(cons), 2, msg=cons)
if LINUX or FREEBSD or SUNOS:
# remote path is never set
self.assertEqual(cons[0].raddr, "")
@ -257,12 +347,58 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
server.close()
client.close()
@skip_on_access_denied(only_if=OSX)
class TestFilters(Base, unittest.TestCase):
def test_filters(self):
def check(kind, families, types):
for conn in thisproc.connections(kind=kind):
self.assertIn(conn.family, families)
self.assertIn(conn.type, types)
if not SKIP_SYSCONS:
for conn in psutil.net_connections(kind=kind):
self.assertIn(conn.family, families)
self.assertIn(conn.type, types)
with create_sockets():
check('all',
[AF_INET, AF_INET6, AF_UNIX],
[SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET])
check('inet',
[AF_INET, AF_INET6],
[SOCK_STREAM, SOCK_DGRAM])
check('inet4',
[AF_INET],
[SOCK_STREAM, SOCK_DGRAM])
check('tcp',
[AF_INET, AF_INET6],
[SOCK_STREAM])
check('tcp4',
[AF_INET],
[SOCK_STREAM])
check('tcp6',
[AF_INET6],
[SOCK_STREAM])
check('udp',
[AF_INET, AF_INET6],
[SOCK_DGRAM])
check('udp4',
[AF_INET],
[SOCK_DGRAM])
check('udp6',
[AF_INET6],
[SOCK_DGRAM])
if HAS_CONNECTIONS_UNIX:
check('unix',
[AF_UNIX],
[SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET])
@skip_on_access_denied(only_if=MACOS)
def test_combos(self):
def check_conn(proc, conn, family, type, laddr, raddr, status, kinds):
all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4",
"tcp6", "udp", "udp4", "udp6")
check_connection_ntuple(conn)
self.check_connection_ntuple(conn)
self.assertEqual(conn.family, family)
self.assertEqual(conn.type, type)
self.assertEqual(conn.laddr, laddr)
@ -284,7 +420,7 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
import socket, time
s = socket.socket($family, socket.SOCK_STREAM)
s.bind(('$addr', 0))
s.listen(1)
s.listen(5)
with open('$testfn', 'w') as f:
f.write(str(s.getsockname()[:2]))
time.sleep(60)
@ -352,13 +488,8 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
psutil.CONN_NONE,
("all", "inet", "inet6", "udp", "udp6"))
# err
self.assertRaises(ValueError, p.connections, kind='???')
def test_multi_sockets_filtering(self):
with create_sockets() as socks:
cons = thisproc.connections(kind='all')
self.assertEqual(len(cons), len(socks))
def test_count(self):
with create_sockets():
# tcp
cons = thisproc.connections(kind='tcp')
self.assertEqual(len(cons), 2 if supports_ipv6() else 1)
@ -406,8 +537,9 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
for conn in cons:
self.assertEqual(conn.family, AF_INET6)
self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM))
# unix
if HAS_CONNECTIONS_UNIX:
# Skipped on BSD becayse by default the Python process
# creates a UNIX socket to '/var/run/log'.
if HAS_CONNECTIONS_UNIX and not (FREEBSD or NETBSD):
cons = thisproc.connections(kind='unix')
self.assertEqual(len(cons), 3)
for conn in cons:
@ -415,23 +547,17 @@ class TestConnectedSocketPairs(Base, unittest.TestCase):
self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM))
# =====================================================================
# --- Miscellaneous tests
# =====================================================================
@unittest.skipIf(SKIP_SYSCONS, "requires root")
class TestSystemWideConnections(Base, unittest.TestCase):
"""Tests for net_connections()."""
@skip_on_access_denied()
def test_it(self):
def check(cons, families, types_):
AF_UNIX = getattr(socket, 'AF_UNIX', object())
for conn in cons:
self.assertIn(conn.family, families, msg=conn)
if conn.family != AF_UNIX:
self.assertIn(conn.type, types_, msg=conn)
check_connection_ntuple(conn)
self.check_connection_ntuple(conn)
with create_sockets():
from psutil._common import conn_tmap
@ -444,18 +570,8 @@ class TestSystemWideConnections(Base, unittest.TestCase):
self.assertEqual(len(cons), len(set(cons)))
check(cons, families, types_)
self.assertRaises(ValueError, psutil.net_connections, kind='???')
@skip_on_access_denied()
def test_multi_socks(self):
with create_sockets() as socks:
cons = [x for x in psutil.net_connections(kind='all')
if x.pid == os.getpid()]
self.assertEqual(len(cons), len(socks))
@skip_on_access_denied()
# See: https://travis-ci.org/giampaolo/psutil/jobs/237566297
@unittest.skipIf(OSX and TRAVIS, "unreliable on OSX + TRAVIS")
@unittest.skipIf(MACOS and TRAVIS, "unreliable on MACOS + TRAVIS")
def test_multi_sockets_procs(self):
# Creates multiple sub processes, each creating different
# sockets. For each process check that proc.connections()
@ -473,7 +589,7 @@ class TestSystemWideConnections(Base, unittest.TestCase):
import time, os
from psutil.tests import create_sockets
with create_sockets():
with open('%s', 'w') as f:
with open(r'%s', 'w') as f:
f.write(str(os.getpid()))
time.sleep(60)
""" % fname)
@ -495,11 +611,6 @@ class TestSystemWideConnections(Base, unittest.TestCase):
self.assertEqual(len(p.connections('all')), expected)
# =====================================================================
# --- Miscellaneous tests
# =====================================================================
class TestMisc(unittest.TestCase):
def test_connection_constants(self):
@ -522,4 +633,5 @@ class TestMisc(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -14,35 +14,32 @@ import os
import stat
import time
import traceback
import warnings
from contextlib import closing
from psutil import AIX
from psutil import BSD
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import callable
from psutil._compat import long
from psutil.tests import bind_unix_socket
from psutil.tests import check_connection_ntuple
from psutil.tests import create_sockets
from psutil.tests import enum
from psutil.tests import get_kernel_version
from psutil.tests import HAS_CONNECTIONS_UNIX
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_RLIMIT
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import is_namedtuple
from psutil.tests import run_test_module_by_name
from psutil.tests import safe_rmpath
from psutil.tests import skip_on_access_denied
from psutil.tests import SKIP_SYSCONS
from psutil.tests import TESTFN
from psutil.tests import unittest
from psutil.tests import unix_socket_path
from psutil.tests import VALID_PROC_STATUSES
from psutil.tests import warn
import psutil
@ -52,19 +49,10 @@ import psutil
# --- APIs availability
# ===================================================================
# Make sure code reflects what doc promises in terms of APIs
# availability.
class TestAvailability(unittest.TestCase):
"""Make sure code reflects what doc promises in terms of APIs
availability.
"""
def test_cpu_affinity(self):
hasit = LINUX or WINDOWS or FREEBSD
self.assertEqual(hasattr(psutil.Process, "cpu_affinity"), hasit)
def test_win_service(self):
self.assertEqual(hasattr(psutil, "win_service_iter"), WINDOWS)
self.assertEqual(hasattr(psutil, "win_service_get"), WINDOWS)
class TestAvailConstantsAPIs(unittest.TestCase):
def test_PROCFS_PATH(self):
self.assertEqual(hasattr(psutil, "PROCFS_PATH"),
@ -79,13 +67,20 @@ class TestAvailability(unittest.TestCase):
ae(hasattr(psutil, "NORMAL_PRIORITY_CLASS"), WINDOWS)
ae(hasattr(psutil, "REALTIME_PRIORITY_CLASS"), WINDOWS)
def test_linux_ioprio(self):
def test_linux_ioprio_linux(self):
ae = self.assertEqual
ae(hasattr(psutil, "IOPRIO_CLASS_NONE"), LINUX)
ae(hasattr(psutil, "IOPRIO_CLASS_RT"), LINUX)
ae(hasattr(psutil, "IOPRIO_CLASS_BE"), LINUX)
ae(hasattr(psutil, "IOPRIO_CLASS_IDLE"), LINUX)
def test_linux_ioprio_windows(self):
ae = self.assertEqual
ae(hasattr(psutil, "IOPRIO_HIGH"), WINDOWS)
ae(hasattr(psutil, "IOPRIO_NORMAL"), WINDOWS)
ae(hasattr(psutil, "IOPRIO_LOW"), WINDOWS)
ae(hasattr(psutil, "IOPRIO_VERYLOW"), WINDOWS)
def test_linux_rlimit(self):
ae = self.assertEqual
hasit = LINUX and get_kernel_version() >= (2, 6, 36)
@ -110,78 +105,77 @@ class TestAvailability(unittest.TestCase):
ae(hasattr(psutil, "RLIMIT_RTTIME"), hasit)
ae(hasattr(psutil, "RLIMIT_SIGPENDING"), hasit)
class TestAvailSystemAPIs(unittest.TestCase):
def test_win_service_iter(self):
self.assertEqual(hasattr(psutil, "win_service_iter"), WINDOWS)
def test_win_service_get(self):
self.assertEqual(hasattr(psutil, "win_service_get"), WINDOWS)
def test_cpu_freq(self):
linux = (LINUX and
(os.path.exists("/sys/devices/system/cpu/cpufreq") or
os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq")))
self.assertEqual(hasattr(psutil, "cpu_freq"), linux or OSX or WINDOWS)
self.assertEqual(hasattr(psutil, "cpu_freq"),
linux or MACOS or WINDOWS or FREEBSD)
def test_sensors_temperatures(self):
self.assertEqual(hasattr(psutil, "sensors_temperatures"), LINUX)
self.assertEqual(
hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD)
def test_sensors_fans(self):
self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX)
def test_battery(self):
self.assertEqual(hasattr(psutil, "sensors_battery"),
LINUX or WINDOWS or FREEBSD or OSX)
LINUX or WINDOWS or FREEBSD or MACOS)
def test_proc_environ(self):
class TestAvailProcessAPIs(unittest.TestCase):
def test_environ(self):
self.assertEqual(hasattr(psutil.Process, "environ"),
LINUX or OSX or WINDOWS)
LINUX or MACOS or WINDOWS or AIX or SUNOS)
def test_proc_uids(self):
def test_uids(self):
self.assertEqual(hasattr(psutil.Process, "uids"), POSIX)
def test_proc_gids(self):
def test_gids(self):
self.assertEqual(hasattr(psutil.Process, "uids"), POSIX)
def test_proc_terminal(self):
def test_terminal(self):
self.assertEqual(hasattr(psutil.Process, "terminal"), POSIX)
def test_proc_ionice(self):
def test_ionice(self):
self.assertEqual(hasattr(psutil.Process, "ionice"), LINUX or WINDOWS)
def test_proc_rlimit(self):
def test_rlimit(self):
self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX)
def test_proc_io_counters(self):
def test_io_counters(self):
hasit = hasattr(psutil.Process, "io_counters")
self.assertEqual(hasit, False if OSX or SUNOS else True)
self.assertEqual(hasit, False if MACOS or SUNOS else True)
def test_proc_num_fds(self):
def test_num_fds(self):
self.assertEqual(hasattr(psutil.Process, "num_fds"), POSIX)
def test_proc_num_handles(self):
def test_num_handles(self):
self.assertEqual(hasattr(psutil.Process, "num_handles"), WINDOWS)
def test_proc_cpu_affinity(self):
def test_cpu_affinity(self):
self.assertEqual(hasattr(psutil.Process, "cpu_affinity"),
LINUX or WINDOWS or FREEBSD)
def test_proc_cpu_num(self):
def test_cpu_num(self):
self.assertEqual(hasattr(psutil.Process, "cpu_num"),
LINUX or FREEBSD or SUNOS)
def test_proc_memory_maps(self):
def test_memory_maps(self):
hasit = hasattr(psutil.Process, "memory_maps")
self.assertEqual(hasit, False if OPENBSD or NETBSD or AIX else True)
# ===================================================================
# --- Test deprecations
# ===================================================================
class TestDeprecations(unittest.TestCase):
def test_memory_info_ex(self):
with warnings.catch_warnings(record=True) as ws:
psutil.Process().memory_info_ex()
w = ws[0]
self.assertIsInstance(w.category(), FutureWarning)
self.assertIn("memory_info_ex() is deprecated", str(w.message))
self.assertIn("use memory_info() instead", str(w.message))
self.assertEqual(
hasit, False if OPENBSD or NETBSD or AIX or MACOS else True)
# ===================================================================
@ -189,7 +183,7 @@ class TestDeprecations(unittest.TestCase):
# ===================================================================
class TestSystem(unittest.TestCase):
class TestSystemAPITypes(unittest.TestCase):
"""Check the return types of system related APIs.
Mainly we want to test we never return unicode on Python 2, see:
https://github.com/giampaolo/psutil/issues/1039
@ -202,18 +196,40 @@ class TestSystem(unittest.TestCase):
def tearDown(self):
safe_rmpath(TESTFN)
def test_cpu_times(self):
# Duplicate of test_system.py. Keep it anyway.
ret = psutil.cpu_times()
assert is_namedtuple(ret)
for n in ret:
self.assertIsInstance(n, float)
self.assertGreaterEqual(n, 0)
def assert_ntuple_of_nums(self, nt, type_=float, gezero=True):
assert is_namedtuple(nt)
for n in nt:
self.assertIsInstance(n, type_)
if gezero:
self.assertGreaterEqual(n, 0)
def test_io_counters(self):
def test_cpu_times(self):
self.assert_ntuple_of_nums(psutil.cpu_times())
for nt in psutil.cpu_times(percpu=True):
self.assert_ntuple_of_nums(nt)
def test_cpu_percent(self):
self.assertIsInstance(psutil.cpu_percent(interval=None), float)
self.assertIsInstance(psutil.cpu_percent(interval=0.00001), float)
def test_cpu_times_percent(self):
self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=None))
self.assert_ntuple_of_nums(psutil.cpu_times_percent(interval=0.0001))
def test_cpu_count(self):
self.assertIsInstance(psutil.cpu_count(), int)
@unittest.skipIf(not HAS_CPU_FREQ, "not supported")
def test_cpu_freq(self):
if psutil.cpu_freq() is None:
raise self.skipTest("cpu_freq() returns None")
self.assert_ntuple_of_nums(psutil.cpu_freq(), type_=(float, int, long))
def test_disk_io_counters(self):
# Duplicate of test_system.py. Keep it anyway.
for k in psutil.disk_io_counters(perdisk=True):
for k, v in psutil.disk_io_counters(perdisk=True).items():
self.assertIsInstance(k, str)
self.assert_ntuple_of_nums(v, type_=(int, long))
def test_disk_partitions(self):
# Duplicate of test_system.py. Keep it anyway.
@ -223,31 +239,40 @@ class TestSystem(unittest.TestCase):
self.assertIsInstance(disk.fstype, str)
self.assertIsInstance(disk.opts, str)
@unittest.skipIf(not POSIX, 'POSIX only')
@unittest.skipIf(not HAS_CONNECTIONS_UNIX, "can't list UNIX sockets")
@skip_on_access_denied(only_if=OSX)
@unittest.skipIf(SKIP_SYSCONS, "requires root")
def test_net_connections(self):
with unix_socket_path() as name:
with closing(bind_unix_socket(name)):
cons = psutil.net_connections(kind='unix')
assert cons
for conn in cons:
self.assertIsInstance(conn.laddr, str)
with create_sockets():
ret = psutil.net_connections('all')
self.assertEqual(len(ret), len(set(ret)))
for conn in ret:
assert is_namedtuple(conn)
def test_net_if_addrs(self):
# Duplicate of test_system.py. Keep it anyway.
for ifname, addrs in psutil.net_if_addrs().items():
self.assertIsInstance(ifname, str)
for addr in addrs:
if enum is not None:
assert isinstance(addr.family, enum.IntEnum), addr
else:
assert isinstance(addr.family, int), addr
self.assertIsInstance(addr.address, str)
self.assertIsInstance(addr.netmask, (str, type(None)))
self.assertIsInstance(addr.broadcast, (str, type(None)))
def test_net_if_stats(self):
# Duplicate of test_system.py. Keep it anyway.
for ifname, _ in psutil.net_if_stats().items():
for ifname, info in psutil.net_if_stats().items():
self.assertIsInstance(ifname, str)
self.assertIsInstance(info.isup, bool)
if enum is not None:
self.assertIsInstance(info.duplex, enum.IntEnum)
else:
self.assertIsInstance(info.duplex, int)
self.assertIsInstance(info.speed, int)
self.assertIsInstance(info.mtu, int)
@unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
def test_net_io_counters(self):
# Duplicate of test_system.py. Keep it anyway.
for ifname, _ in psutil.net_io_counters(pernic=True).items():
@ -260,6 +285,7 @@ class TestSystem(unittest.TestCase):
self.assertIsInstance(name, str)
for unit in units:
self.assertIsInstance(unit.label, str)
self.assertIsInstance(unit.current, (float, int, type(None)))
@unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported")
def test_sensors_temperatures(self):
@ -268,6 +294,13 @@ class TestSystem(unittest.TestCase):
self.assertIsInstance(name, str)
for unit in units:
self.assertIsInstance(unit.label, str)
self.assertIsInstance(unit.current, (float, int, type(None)))
self.assertIsInstance(unit.high, (float, int, type(None)))
self.assertIsInstance(unit.critical, (float, int, type(None)))
def test_boot_time(self):
# Duplicate of test_system.py. Keep it anyway.
self.assertIsInstance(psutil.boot_time(), float)
def test_users(self):
# Duplicate of test_system.py. Keep it anyway.
@ -288,21 +321,11 @@ class TestFetchAllProcesses(unittest.TestCase):
some sanity checks against Process API's returned values.
"""
def setUp(self):
if POSIX:
import pwd
import grp
users = pwd.getpwall()
groups = grp.getgrall()
self.all_uids = set([x.pw_uid for x in users])
self.all_usernames = set([x.pw_name for x in users])
self.all_gids = set([x.gr_gid for x in groups])
def test_fetch_all(self):
valid_procs = 0
def get_attr_names(self):
excluded_names = set([
'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait',
'as_dict', 'parent', 'children', 'memory_info_ex', 'oneshot',
'as_dict', 'parent', 'parents', 'children', 'memory_info_ex',
'oneshot',
])
if LINUX and not HAS_RLIMIT:
excluded_names.add('rlimit')
@ -313,55 +336,66 @@ class TestFetchAllProcesses(unittest.TestCase):
if name in excluded_names:
continue
attrs.append(name)
return attrs
default = object()
failures = []
def iter_procs(self):
attrs = self.get_attr_names()
for p in psutil.process_iter():
with p.oneshot():
for name in attrs:
ret = default
try:
args = ()
kwargs = {}
attr = getattr(p, name, None)
if attr is not None and callable(attr):
if name == 'rlimit':
args = (psutil.RLIMIT_NOFILE,)
elif name == 'memory_maps':
kwargs = {'grouped': False}
ret = attr(*args, **kwargs)
else:
ret = attr
valid_procs += 1
except NotImplementedError:
msg = "%r was skipped because not implemented" % (
self.__class__.__name__ + '.test_' + name)
warn(msg)
except (psutil.NoSuchProcess, psutil.AccessDenied) as err:
self.assertEqual(err.pid, p.pid)
if err.name:
# make sure exception's name attr is set
# with the actual process name
self.assertEqual(err.name, p.name())
assert str(err)
assert err.msg
except Exception as err:
s = '\n' + '=' * 70 + '\n'
s += "FAIL: test_%s (proc=%s" % (name, p)
if ret != default:
s += ", ret=%s)" % repr(ret)
s += ')\n'
s += '-' * 70
s += "\n%s" % traceback.format_exc()
s = "\n".join((" " * 4) + i for i in s.splitlines())
s += '\n'
failures.append(s)
break
else:
if ret not in (0, 0.0, [], None, '', {}):
assert ret, ret
meth = getattr(self, name)
meth(ret, p)
yield (p, name)
def call_meth(self, p, name):
args = ()
kwargs = {}
attr = getattr(p, name, None)
if attr is not None and callable(attr):
if name == 'rlimit':
args = (psutil.RLIMIT_NOFILE,)
elif name == 'memory_maps':
kwargs = {'grouped': False}
return attr(*args, **kwargs)
else:
return attr
def test_fetch_all(self):
valid_procs = 0
default = object()
failures = []
for p, name in self.iter_procs():
ret = default
try:
ret = self.call_meth(p, name)
except NotImplementedError:
msg = "%r was skipped because not implemented" % (
self.__class__.__name__ + '.test_' + name)
warn(msg)
except (psutil.NoSuchProcess, psutil.AccessDenied) as err:
self.assertEqual(err.pid, p.pid)
if err.name:
# make sure exception's name attr is set
# with the actual process name
self.assertEqual(err.name, p.name())
assert str(err)
assert err.msg
except Exception:
s = '\n' + '=' * 70 + '\n'
s += "FAIL: test_%s (proc=%s" % (name, p)
if ret != default:
s += ", ret=%s)" % repr(ret)
s += ')\n'
s += '-' * 70
s += "\n%s" % traceback.format_exc()
s = "\n".join((" " * 4) + i for i in s.splitlines())
s += '\n'
failures.append(s)
break
else:
valid_procs += 1
if ret not in (0, 0.0, [], None, '', {}):
assert ret, ret
meth = getattr(self, name)
meth(ret, p)
if failures:
self.fail(''.join(failures))
@ -380,13 +414,15 @@ class TestFetchAllProcesses(unittest.TestCase):
if not ret:
self.assertEqual(ret, '')
else:
if WINDOWS and not ret.endswith('.exe'):
return # May be "Registry", "MemCompression", ...
assert os.path.isabs(ret), ret
# Note: os.stat() may return False even if the file is there
# hence we skip the test, see:
# http://stackoverflow.com/questions/3112546/os-path-exists-lies
if POSIX and os.path.isfile(ret):
if hasattr(os, 'access') and hasattr(os, "X_OK"):
# XXX may fail on OSX
# XXX may fail on MACOS
assert os.access(ret, os.X_OK)
def pid(self, ret, proc):
@ -424,7 +460,6 @@ class TestFetchAllProcesses(unittest.TestCase):
for uid in ret:
self.assertIsInstance(uid, int)
self.assertGreaterEqual(uid, 0)
self.assertIn(uid, self.all_uids)
def gids(self, ret, proc):
assert is_namedtuple(ret)
@ -432,15 +467,12 @@ class TestFetchAllProcesses(unittest.TestCase):
# gid == 30 (nodoby); not sure why.
for gid in ret:
self.assertIsInstance(gid, int)
if not OSX and not NETBSD:
if not MACOS and not NETBSD:
self.assertGreaterEqual(gid, 0)
self.assertIn(gid, self.all_gids)
def username(self, ret, proc):
self.assertIsInstance(ret, str)
assert ret
if POSIX:
self.assertIn(ret, self.all_usernames)
def status(self, ret, proc):
self.assertIsInstance(ret, str)
@ -456,16 +488,20 @@ class TestFetchAllProcesses(unittest.TestCase):
self.assertGreaterEqual(field, 0)
def ionice(self, ret, proc):
if POSIX:
assert is_namedtuple(ret)
for field in ret:
self.assertIsInstance(field, int)
if LINUX:
self.assertIsInstance(ret.ioclass, int)
self.assertIsInstance(ret.value, int)
self.assertGreaterEqual(ret.ioclass, 0)
self.assertGreaterEqual(ret.value, 0)
else:
else: # Windows, Cygwin
choices = [
psutil.IOPRIO_VERYLOW,
psutil.IOPRIO_LOW,
psutil.IOPRIO_NORMAL,
psutil.IOPRIO_HIGH]
self.assertIsInstance(ret, int)
self.assertGreaterEqual(ret, 0)
self.assertIn(ret, (0, 1, 2))
self.assertIn(ret, choices)
def num_threads(self, ret, proc):
self.assertIsInstance(ret, int)
@ -506,13 +542,7 @@ class TestFetchAllProcesses(unittest.TestCase):
for value in ret:
self.assertIsInstance(value, (int, long))
self.assertGreaterEqual(value, 0)
if POSIX and not AIX and ret.vms != 0:
# VMS is always supposed to be the highest
for name in ret._fields:
if name != 'vms':
value = getattr(ret, name)
self.assertGreater(ret.vms, value, msg=ret)
elif WINDOWS:
if WINDOWS:
self.assertGreaterEqual(ret.peak_wset, ret.wset)
self.assertGreaterEqual(ret.peak_paged_pool, ret.paged_pool)
self.assertGreaterEqual(ret.peak_nonpaged_pool, ret.nonpaged_pool)
@ -525,6 +555,10 @@ class TestFetchAllProcesses(unittest.TestCase):
value = getattr(ret, name)
self.assertIsInstance(value, (int, long))
self.assertGreaterEqual(value, 0, msg=(name, value))
if LINUX or OSX and name in ('vms', 'data'):
# On Linux there are processes (e.g. 'goa-daemon') whose
# VMS is incredibly high for some reason.
continue
self.assertLessEqual(value, total, msg=(name, value, total))
if LINUX:
@ -555,9 +589,10 @@ class TestFetchAllProcesses(unittest.TestCase):
self.assertGreaterEqual(ret, 0)
def connections(self, ret, proc):
self.assertEqual(len(ret), len(set(ret)))
for conn in ret:
check_connection_ntuple(conn)
with create_sockets():
self.assertEqual(len(ret), len(set(ret)))
for conn in ret:
assert is_namedtuple(conn)
def cwd(self, ret, proc):
if ret: # 'ret' can be None or empty
@ -609,8 +644,11 @@ class TestFetchAllProcesses(unittest.TestCase):
# commented as on Linux we might get
# '/foo/bar (deleted)'
# assert os.path.exists(nt.path), nt.path
elif fname in ('addr', 'perms'):
assert value
elif fname == 'addr':
assert value, repr(value)
elif fname == 'perms':
if not WINDOWS:
assert value, repr(value)
else:
self.assertIsInstance(value, (int, long))
self.assertGreaterEqual(value, 0)
@ -648,4 +686,5 @@ class TestFetchAllProcesses(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -11,10 +11,11 @@ checking whether process memory usage keeps increasing between
calls or over time.
Note that this may produce false positives (especially on Windows
for some reason).
PyPy appears to be completely unstable for this framework, probably
because of how its JIT handles memory, so tests are skipped.
"""
from __future__ import print_function
import errno
import functools
import gc
import os
@ -24,13 +25,17 @@ import time
import psutil
import psutil._common
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import bytes2human
from psutil._compat import ProcessLookupError
from psutil._compat import xrange
from psutil.tests import CIRRUS
from psutil.tests import create_sockets
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_CPU_AFFINITY
@ -38,14 +43,15 @@ from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_IONICE
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_PROC_CPU_NUM
from psutil.tests import HAS_PROC_IO_COUNTERS
from psutil.tests import HAS_RLIMIT
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import PYPY
from psutil.tests import reap_children
from psutil.tests import run_test_module_by_name
from psutil.tests import safe_rmpath
from psutil.tests import skip_on_access_denied
from psutil.tests import TESTFN
@ -53,14 +59,14 @@ from psutil.tests import TRAVIS
from psutil.tests import unittest
# configurable opts
LOOPS = 1000
MEMORY_TOLERANCE = 4096
RETRY_FOR = 3
SKIP_PYTHON_IMPL = True
SKIP_PYTHON_IMPL = True if TRAVIS else False
cext = psutil._psplatform.cext
thisproc = psutil.Process()
SKIP_PYTHON_IMPL = True if TRAVIS else False
# ===================================================================
@ -73,25 +79,7 @@ def skip_if_linux():
"worthless on LINUX (pure python)")
def bytes2human(n):
"""
http://code.activestate.com/recipes/578019
>>> bytes2human(10000)
'9.8K'
>>> bytes2human(100001221)
'95.4M'
"""
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.2f%s' % (value, s)
return "%sB" % n
@unittest.skipIf(PYPY, "unreliable on PYPY")
class TestMemLeak(unittest.TestCase):
"""Base framework class which calls a function many times and
produces a failure if process memory usage keeps increasing
@ -176,7 +164,7 @@ class TestMemLeak(unittest.TestCase):
def _get_mem():
# By using USS memory it seems it's less likely to bump
# into false positives.
if LINUX or WINDOWS or OSX:
if LINUX or WINDOWS or MACOS:
return thisproc.memory_full_info().uss
else:
return thisproc.memory_info().rss
@ -200,8 +188,8 @@ class TestProcessObjectLeaks(TestMemLeak):
skip = set((
"pid", "as_dict", "children", "cpu_affinity", "cpu_percent",
"ionice", "is_running", "kill", "memory_info_ex", "memory_percent",
"nice", "oneshot", "parent", "rlimit", "send_signal", "suspend",
"terminate", "wait"))
"nice", "oneshot", "parent", "parents", "rlimit", "send_signal",
"suspend", "terminate", "wait"))
for name in dir(psutil.Process):
if name.startswith('_'):
continue
@ -344,8 +332,6 @@ class TestProcessObjectLeaks(TestMemLeak):
with open(TESTFN, 'w'):
self.execute(self.proc.open_files)
# OSX implementation is unbelievably slow
@unittest.skipIf(OSX, "too slow on OSX")
@unittest.skipIf(not HAS_MEMORY_MAPS, "not supported")
@skip_if_linux()
def test_memory_maps(self):
@ -384,6 +370,16 @@ class TestProcessObjectLeaks(TestMemLeak):
self.execute(cext.proc_info, os.getpid())
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestProcessDualImplementation(TestMemLeak):
def test_cmdline_peb_true(self):
self.execute(cext.proc_cmdline, os.getpid(), use_peb=True)
def test_cmdline_peb_false(self):
self.execute(cext.proc_cmdline, os.getpid(), use_peb=False)
class TestTerminatedProcessLeaks(TestProcessObjectLeaks):
"""Repeat the tests above looking for leaks occurring when dealing
with terminated processes raising NoSuchProcess exception.
@ -432,9 +428,8 @@ class TestTerminatedProcessLeaks(TestProcessObjectLeaks):
def call():
try:
return cext.proc_info(self.proc.pid)
except OSError as err:
if err.errno != errno.ESRCH:
raise
except ProcessLookupError:
pass
self.execute(call)
@ -476,6 +471,7 @@ class TestModuleFunctionsLeaks(TestMemLeak):
def test_per_cpu_times(self):
self.execute(psutil.cpu_times, percpu=True)
@skip_if_linux()
def test_cpu_stats(self):
self.execute(psutil.cpu_stats)
@ -484,14 +480,17 @@ class TestModuleFunctionsLeaks(TestMemLeak):
def test_cpu_freq(self):
self.execute(psutil.cpu_freq)
@unittest.skipIf(not WINDOWS, "WINDOWS only")
def test_getloadavg(self):
self.execute(psutil.getloadavg)
# --- mem
def test_virtual_memory(self):
self.execute(psutil.virtual_memory)
# TODO: remove this skip when this gets fixed
@unittest.skipIf(SUNOS,
"worthless on SUNOS (uses a subprocess)")
@unittest.skipIf(SUNOS, "worthless on SUNOS (uses a subprocess)")
def test_swap_memory(self):
self.execute(psutil.swap_memory)
@ -524,13 +523,15 @@ class TestModuleFunctionsLeaks(TestMemLeak):
# --- net
@unittest.skipIf(TRAVIS and MACOS, "false positive on TRAVIS + MACOS")
@unittest.skipIf(CIRRUS and FREEBSD, "false positive on CIRRUS + FREEBSD")
@skip_if_linux()
@unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
def test_net_io_counters(self):
self.execute(psutil.net_io_counters, nowrap=False)
@unittest.skipIf(LINUX,
"worthless on Linux (pure python)")
@unittest.skipIf(OSX and os.getuid() != 0, "need root access")
@skip_if_linux()
@unittest.skipIf(MACOS and os.getuid() != 0, "need root access")
def test_net_connections(self):
with create_sockets():
self.execute(psutil.net_connections)
@ -567,7 +568,6 @@ class TestModuleFunctionsLeaks(TestMemLeak):
def test_boot_time(self):
self.execute(psutil.boot_time)
# XXX - on Windows this produces a false positive
@unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows")
def test_users(self):
self.execute(psutil.users)
@ -596,4 +596,5 @@ class TestModuleFunctionsLeaks(TestMemLeak):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
@ -19,19 +19,24 @@ import pickle
import socket
import stat
from psutil import FREEBSD
from psutil import LINUX
from psutil import NETBSD
from psutil import POSIX
from psutil import WINDOWS
from psutil._common import memoize
from psutil._common import memoize_when_activated
from psutil._common import supports_ipv6
from psutil._common import wrap_numbers
from psutil._common import open_text
from psutil._common import open_binary
from psutil._compat import PY3
from psutil.tests import APPVEYOR
from psutil.tests import bind_socket
from psutil.tests import bind_unix_socket
from psutil.tests import call_until
from psutil.tests import chdir
from psutil.tests import CI_TESTING
from psutil.tests import create_proc_children_pair
from psutil.tests import create_sockets
from psutil.tests import create_zombie_proc
@ -40,8 +45,8 @@ from psutil.tests import get_free_port
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_CONNECTIONS_UNIX
from psutil.tests import HAS_MEMORY_FULL_INFO
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
@ -53,7 +58,7 @@ from psutil.tests import reap_children
from psutil.tests import reload_module
from psutil.tests import retry
from psutil.tests import ROOT_DIR
from psutil.tests import run_test_module_by_name
from psutil.tests import safe_mkdir
from psutil.tests import safe_rmpath
from psutil.tests import SCRIPTS_DIR
from psutil.tests import sh
@ -177,7 +182,8 @@ class TestMisc(unittest.TestCase):
for name in dir_psutil:
if name in ('callable', 'error', 'namedtuple', 'tests',
'long', 'test', 'NUM_CPUS', 'BOOT_TIME',
'TOTAL_PHYMEM'):
'TOTAL_PHYMEM', 'PermissionError',
'ProcessLookupError'):
continue
if not name.startswith('_'):
try:
@ -258,14 +264,14 @@ class TestMisc(unittest.TestCase):
# activate
calls = []
f.foo.cache_activate()
f.foo.cache_activate(f)
f.foo()
f.foo()
self.assertEqual(len(calls), 1)
# deactivate
calls = []
f.foo.cache_deactivate()
f.foo.cache_deactivate(f)
f.foo()
f.foo()
self.assertEqual(len(calls), 2)
@ -617,10 +623,10 @@ class TestWrapNumbers(unittest.TestCase):
wrap_numbers.cache_clear('disk_io')
wrap_numbers.cache_clear('?!?')
@unittest.skipIf(
not psutil.disk_io_counters() or not psutil.net_io_counters(),
"no disks or NICs available")
@unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
def test_cache_clear_public_apis(self):
if not psutil.disk_io_counters() or not psutil.net_io_counters():
return self.skipTest("no disks or NICs available")
psutil.disk_io_counters()
psutil.net_io_counters()
caches = wrap_numbers.cache_info()
@ -708,9 +714,7 @@ class TestScripts(unittest.TestCase):
def test_procinfo(self):
self.assert_stdout('procinfo.py', str(os.getpid()))
# can't find users on APPVEYOR or TRAVIS
@unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(),
"unreliable on APPVEYOR or TRAVIS")
@unittest.skipIf(CI_TESTING and not psutil.users(), "no users")
def test_who(self):
self.assert_stdout('who.py')
@ -732,8 +736,9 @@ class TestScripts(unittest.TestCase):
def test_pmap(self):
self.assert_stdout('pmap.py', str(os.getpid()))
@unittest.skipIf(not HAS_MEMORY_FULL_INFO, "not supported")
def test_procsmem(self):
if 'uss' not in psutil.Process().memory_full_info()._fields:
raise self.skipTest("not supported")
self.assert_stdout('procsmem.py', stderr=DEVNULL)
def test_killall(self):
@ -762,11 +767,15 @@ class TestScripts(unittest.TestCase):
@unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported")
@unittest.skipIf(TRAVIS, "unreliable on TRAVIS")
def test_temperatures(self):
if not psutil.sensors_temperatures():
self.skipTest("no temperatures")
self.assert_stdout('temperatures.py')
@unittest.skipIf(not HAS_SENSORS_FANS, "not supported")
@unittest.skipIf(TRAVIS, "unreliable on TRAVIS")
def test_fans(self):
if not psutil.sensors_fans():
self.skipTest("no fans")
self.assert_stdout('fans.py')
@unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported")
@ -895,6 +904,20 @@ class TestFSTestUtils(unittest.TestCase):
tearDown = setUp
def test_open_text(self):
with open_text(__file__) as f:
self.assertEqual(f.mode, 'rt')
def test_open_binary(self):
with open_binary(__file__) as f:
self.assertEqual(f.mode, 'rb')
def test_safe_mkdir(self):
safe_mkdir(TESTFN)
assert os.path.isdir(TESTFN)
safe_mkdir(TESTFN)
assert os.path.isdir(TESTFN)
def test_safe_rmpath(self):
# test file is removed
open(TESTFN, 'w').close()
@ -994,6 +1017,8 @@ class TestNetUtils(unittest.TestCase):
self.assertNotEqual(client.getsockname(), addr)
@unittest.skipIf(not POSIX, "POSIX only")
@unittest.skipIf(NETBSD or FREEBSD,
"/var/run/log UNIX socket opened by default")
def test_unix_socketpair(self):
p = psutil.Process()
num_fds = p.num_fds()
@ -1036,4 +1061,5 @@ class TestOtherUtils(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,29 +1,28 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""OSX specific tests."""
"""MACOS specific tests."""
import os
import re
import time
import psutil
from psutil import OSX
from psutil import MACOS
from psutil.tests import create_zombie_proc
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_BATTERY
from psutil.tests import MEMORY_TOLERANCE
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import unittest
PAGESIZE = os.sysconf("SC_PAGE_SIZE") if OSX else None
PAGESIZE = os.sysconf("SC_PAGE_SIZE") if MACOS else None
def sysctl(cmdline):
@ -76,7 +75,7 @@ def human2bytes(s):
return int(num * prefix[letter])
@unittest.skipIf(not OSX, "OSX only")
@unittest.skipIf(not MACOS, "MACOS only")
class TestProcess(unittest.TestCase):
@classmethod
@ -101,7 +100,7 @@ class TestProcess(unittest.TestCase):
time.strftime("%Y", time.localtime(start_psutil)))
@unittest.skipIf(not OSX, "OSX only")
@unittest.skipIf(not MACOS, "MACOS only")
class TestZombieProcessAPIs(unittest.TestCase):
@classmethod
@ -158,11 +157,8 @@ class TestZombieProcessAPIs(unittest.TestCase):
self.assertRaises((psutil.ZombieProcess, psutil.AccessDenied),
self.p.threads)
def test_memory_maps(self):
self.assertRaises(psutil.ZombieProcess, self.p.memory_maps)
@unittest.skipIf(not OSX, "OSX only")
@unittest.skipIf(not MACOS, "MACOS only")
class TestSystemAPIs(unittest.TestCase):
# --- disk
@ -219,31 +215,25 @@ class TestSystemAPIs(unittest.TestCase):
sysctl_hwphymem = sysctl('sysctl hw.memsize')
self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total)
@retry_before_failing()
@retry_on_failure()
def test_vmem_free(self):
vmstat_val = vm_stat("free")
psutil_val = psutil.virtual_memory().free
self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE)
@retry_before_failing()
def test_vmem_available(self):
vmstat_val = vm_stat("inactive") + vm_stat("free")
psutil_val = psutil.virtual_memory().available
self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_active(self):
vmstat_val = vm_stat("active")
psutil_val = psutil.virtual_memory().active
self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_inactive(self):
vmstat_val = vm_stat("inactive")
psutil_val = psutil.virtual_memory().inactive
self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE)
@retry_before_failing()
@retry_on_failure()
def test_vmem_wired(self):
vmstat_val = vm_stat("wired")
psutil_val = psutil.virtual_memory().wired
@ -251,13 +241,13 @@ class TestSystemAPIs(unittest.TestCase):
# --- swap mem
@retry_before_failing()
@retry_on_failure()
def test_swapmem_sin(self):
vmstat_val = vm_stat("Pageins")
psutil_val = psutil.swap_memory().sin
self.assertEqual(psutil_val, vmstat_val)
@retry_before_failing()
@retry_on_failure()
def test_swapmem_sout(self):
vmstat_val = vm_stat("Pageout")
psutil_val = psutil.swap_memory().sout
@ -291,7 +281,7 @@ class TestSystemAPIs(unittest.TestCase):
@unittest.skipIf(not HAS_BATTERY, "no battery")
def test_sensors_battery(self):
out = sh("pmset -g batt")
percent = re.search("(\d+)%", out).group(1)
percent = re.search(r"(\d+)%", out).group(1)
drawing_from = re.search("Now drawing from '([^']+)'", out).group(1)
power_plugged = drawing_from == "AC Power"
psutil_result = psutil.sensors_battery()
@ -300,4 +290,5 @@ class TestSystemAPIs(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
@ -12,27 +12,24 @@ import errno
import os
import re
import subprocess
import sys
import time
import psutil
from psutil import AIX
from psutil import BSD
from psutil import LINUX
from psutil import MACOS
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil._compat import callable
from psutil._compat import PY3
from psutil.tests import APPVEYOR
from psutil.tests import CI_TESTING
from psutil.tests import get_kernel_version
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import mock
from psutil.tests import PYTHON_EXE
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import skip_on_access_denied
from psutil.tests import TRAVIS
@ -41,23 +38,53 @@ from psutil.tests import wait_for_pid
from psutil.tests import which
def ps(cmd):
"""Expects a ps command with a -o argument and parse the result
returning only the value of interest.
def ps(fmt, pid=None):
"""
if not LINUX:
cmd = cmd.replace(" --no-headers ", " ")
Wrapper for calling the ps command with a little bit of cross-platform
support for a narrow range of features.
"""
cmd = ['ps']
if LINUX:
cmd.append('--no-headers')
if pid is not None:
cmd.extend(['-p', str(pid)])
else:
if SUNOS or AIX:
cmd.append('-A')
else:
cmd.append('ax')
if SUNOS:
cmd = cmd.replace("-o start", "-o stime")
if AIX:
cmd = cmd.replace("-o rss", "-o rssize")
fmt_map = set(('command', 'comm', 'start', 'stime'))
fmt = fmt_map.get(fmt, fmt)
cmd.extend(['-o', fmt])
output = sh(cmd)
if not LINUX:
output = output.split('\n')[1].strip()
try:
return int(output)
except ValueError:
return output
if LINUX:
output = output.splitlines()
else:
output = output.splitlines()[1:]
all_output = []
for line in output:
line = line.strip()
try:
line = int(line)
except ValueError:
pass
all_output.append(line)
if pid is None:
return all_output
else:
return all_output[0]
# ps "-o" field names differ wildly between platforms.
# "comm" means "only executable name" but is not available on BSD platforms.
@ -75,14 +102,28 @@ def ps_name(pid):
field = "command"
if SUNOS:
field = "comm"
return ps("ps --no-headers -o %s -p %s" % (field, pid)).split(' ')[0]
return ps(field, pid).split()[0]
def ps_args(pid):
field = "command"
if AIX or SUNOS:
field = "args"
return ps("ps --no-headers -o %s -p %s" % (field, pid))
return ps(field, pid)
def ps_rss(pid):
field = "rss"
if AIX:
field = "rssize"
return ps(field, pid)
def ps_vsz(pid):
field = "vsz"
if AIX:
field = "vsize"
return ps(field, pid)
@unittest.skipIf(not POSIX, "POSIX only")
@ -100,22 +141,22 @@ class TestProcess(unittest.TestCase):
reap_children()
def test_ppid(self):
ppid_ps = ps("ps --no-headers -o ppid -p %s" % self.pid)
ppid_ps = ps('ppid', self.pid)
ppid_psutil = psutil.Process(self.pid).ppid()
self.assertEqual(ppid_ps, ppid_psutil)
def test_uid(self):
uid_ps = ps("ps --no-headers -o uid -p %s" % self.pid)
uid_ps = ps('uid', self.pid)
uid_psutil = psutil.Process(self.pid).uids().real
self.assertEqual(uid_ps, uid_psutil)
def test_gid(self):
gid_ps = ps("ps --no-headers -o rgid -p %s" % self.pid)
gid_ps = ps('rgid', self.pid)
gid_psutil = psutil.Process(self.pid).gids().real
self.assertEqual(gid_ps, gid_psutil)
def test_username(self):
username_ps = ps("ps --no-headers -o user -p %s" % self.pid)
username_ps = ps('user', self.pid)
username_psutil = psutil.Process(self.pid).username()
self.assertEqual(username_ps, username_psutil)
@ -129,22 +170,22 @@ class TestProcess(unittest.TestCase):
assert fun.called
@skip_on_access_denied()
@retry_before_failing()
@retry_on_failure()
def test_rss_memory(self):
# give python interpreter some time to properly initialize
# so that the results are the same
time.sleep(0.1)
rss_ps = ps("ps --no-headers -o rss -p %s" % self.pid)
rss_ps = ps_rss(self.pid)
rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024
self.assertEqual(rss_ps, rss_psutil)
@skip_on_access_denied()
@retry_before_failing()
@retry_on_failure()
def test_vsz_memory(self):
# give python interpreter some time to properly initialize
# so that the results are the same
time.sleep(0.1)
vsz_ps = ps("ps --no-headers -o vsz -p %s" % self.pid)
vsz_ps = ps_vsz(self.pid)
vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024
self.assertEqual(vsz_ps, vsz_psutil)
@ -153,10 +194,13 @@ class TestProcess(unittest.TestCase):
# remove path if there is any, from the command
name_ps = os.path.basename(name_ps).lower()
name_psutil = psutil.Process(self.pid).name().lower()
# ...because of how we calculate PYTHON_EXE; on OSX this may
# ...because of how we calculate PYTHON_EXE; on MACOS this may
# be "pythonX.Y".
name_ps = re.sub(r"\d.\d", "", name_ps)
name_psutil = re.sub(r"\d.\d", "", name_psutil)
# ...may also be "python.X"
name_ps = re.sub(r"\d", "", name_ps)
name_psutil = re.sub(r"\d", "", name_psutil)
self.assertEqual(name_ps, name_psutil)
def test_name_long(self):
@ -195,9 +239,9 @@ class TestProcess(unittest.TestCase):
p = psutil.Process()
self.assertRaises(psutil.NoSuchProcess, p.name)
@unittest.skipIf(OSX or BSD, 'ps -o start not available')
@unittest.skipIf(MACOS or BSD, 'ps -o start not available')
def test_create_time(self):
time_ps = ps("ps --no-headers -o start -p %s" % self.pid).split(' ')[0]
time_ps = ps('start', self.pid)
time_psutil = psutil.Process(self.pid).create_time()
time_psutil_tstamp = datetime.datetime.fromtimestamp(
time_psutil).strftime("%H:%M:%S")
@ -236,7 +280,7 @@ class TestProcess(unittest.TestCase):
@unittest.skipIf(SUNOS, "not reliable on SUNOS")
@unittest.skipIf(AIX, "not reliable on AIX")
def test_nice(self):
ps_nice = ps("ps --no-headers -o nice -p %s" % self.pid)
ps_nice = ps('nice', self.pid)
psutil_nice = psutil.Process().nice()
self.assertEqual(ps_nice, psutil_nice)
@ -257,7 +301,7 @@ class TestProcess(unittest.TestCase):
failures = []
ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice',
'send_signal', 'wait', 'children', 'as_dict',
'memory_info_ex']
'memory_info_ex', 'parent', 'parents']
if LINUX and get_kernel_version() < (2, 6, 36):
ignored_names.append('rlimit')
if LINUX and get_kernel_version() < (2, 6, 23):
@ -286,40 +330,29 @@ class TestProcess(unittest.TestCase):
class TestSystemAPIs(unittest.TestCase):
"""Test some system APIs."""
@retry_before_failing()
@retry_on_failure()
def test_pids(self):
# Note: this test might fail if the OS is starting/killing
# other processes in the meantime
if SUNOS or AIX:
cmd = ["ps", "-A", "-o", "pid"]
else:
cmd = ["ps", "ax", "-o", "pid"]
p = get_test_subprocess(cmd, stdout=subprocess.PIPE)
output = p.communicate()[0].strip()
assert p.poll() == 0
if PY3:
output = str(output, sys.stdout.encoding)
pids_ps = []
for line in output.split('\n')[1:]:
if line:
pid = int(line.split()[0].strip())
pids_ps.append(pid)
# remove ps subprocess pid which is supposed to be dead in meantime
pids_ps.remove(p.pid)
pids_ps = sorted(ps("pid"))
pids_psutil = psutil.pids()
pids_ps.sort()
pids_psutil.sort()
# on OSX and OPENBSD ps doesn't show pid 0
if OSX or OPENBSD and 0 not in pids_ps:
# on MACOS and OPENBSD ps doesn't show pid 0
if MACOS or OPENBSD and 0 not in pids_ps:
pids_ps.insert(0, 0)
self.assertEqual(pids_ps, pids_psutil)
# There will often be one more process in pids_ps for ps itself
if len(pids_ps) - len(pids_psutil) > 1:
difference = [x for x in pids_psutil if x not in pids_ps] + \
[x for x in pids_ps if x not in pids_psutil]
self.fail("difference: " + str(difference))
# for some reason ifconfig -a does not report all interfaces
# returned by psutil
@unittest.skipIf(SUNOS, "unreliable on SUNOS")
@unittest.skipIf(TRAVIS, "unreliable on TRAVIS")
@unittest.skipIf(not which('ifconfig'), "no ifconfig cmd")
@unittest.skipIf(not HAS_NET_IO_COUNTERS, "not supported")
def test_nic_names(self):
output = sh("ifconfig -a")
for nic in psutil.net_io_counters(pernic=True).keys():
@ -331,13 +364,13 @@ class TestSystemAPIs(unittest.TestCase):
"couldn't find %s nic in 'ifconfig -a' output\n%s" % (
nic, output))
# can't find users on APPVEYOR or TRAVIS
@unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(),
"unreliable on APPVEYOR or TRAVIS")
@retry_before_failing()
@unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI")
@retry_on_failure()
def test_users(self):
out = sh("who")
lines = out.split('\n')
if not lines:
raise self.skipTest("no users on this system")
users = [x.split()[0] for x in lines]
terminals = [x.split()[1] for x in lines]
self.assertEqual(len(users), len(psutil.users()))
@ -416,4 +449,5 @@ class TestSystemAPIs(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -25,23 +25,25 @@ import psutil
from psutil import AIX
from psutil import BSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._common import open_text
from psutil._compat import long
from psutil._compat import PY3
from psutil.tests import APPVEYOR
from psutil.tests import call_until
from psutil.tests import CIRRUS
from psutil.tests import copyload_shared_lib
from psutil.tests import create_exe
from psutil.tests import create_proc_children_pair
from psutil.tests import create_zombie_proc
from psutil.tests import enum
from psutil.tests import get_test_subprocess
from psutil.tests import get_winver
from psutil.tests import HAS_CPU_AFFINITY
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_IONICE
@ -54,8 +56,7 @@ from psutil.tests import mock
from psutil.tests import PYPY
from psutil.tests import PYTHON_EXE
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import safe_rmpath
from psutil.tests import sh
from psutil.tests import skip_on_access_denied
@ -66,7 +67,6 @@ from psutil.tests import ThreadTask
from psutil.tests import TRAVIS
from psutil.tests import unittest
from psutil.tests import wait_for_pid
from psutil.tests import WIN_VISTA
# ===================================================================
@ -238,10 +238,6 @@ class TestProcess(unittest.TestCase):
percent = p.cpu_percent(interval=None)
self.assertIsInstance(percent, float)
self.assertGreaterEqual(percent, 0.0)
if not POSIX:
self.assertLessEqual(percent, 100.0)
else:
self.assertGreaterEqual(percent, 0.0)
with self.assertRaises(ValueError):
p.cpu_percent(interval=-1)
@ -256,6 +252,8 @@ class TestProcess(unittest.TestCase):
assert (times.user > 0.0) or (times.system > 0.0), times
assert (times.children_user >= 0.0), times
assert (times.children_system >= 0.0), times
if LINUX:
assert times.iowait >= 0.0, times
# make sure returned values can be pretty printed with strftime
for name in times._fields:
time.strftime("%H:%M:%S", time.localtime(getattr(times, name)))
@ -300,7 +298,7 @@ class TestProcess(unittest.TestCase):
time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time()))
@unittest.skipIf(not POSIX, 'POSIX only')
@unittest.skipIf(TRAVIS, 'not reliable on TRAVIS')
@unittest.skipIf(TRAVIS or CIRRUS, 'not reliable on TRAVIS/CIRRUS')
def test_terminal(self):
terminal = psutil.Process().terminal()
if sys.stdin.isatty() or sys.stdout.isatty():
@ -313,7 +311,6 @@ class TestProcess(unittest.TestCase):
@skip_on_not_implemented(only_if=LINUX)
def test_io_counters(self):
p = psutil.Process()
# test reads
io1 = p.io_counters()
with open(PYTHON_EXE, 'rb') as f:
@ -354,74 +351,77 @@ class TestProcess(unittest.TestCase):
self.assertGreaterEqual(io2[i], 0)
@unittest.skipIf(not HAS_IONICE, "not supported")
@unittest.skipIf(WINDOWS and get_winver() < WIN_VISTA, 'not supported')
def test_ionice(self):
if LINUX:
from psutil import (IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT,
IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE)
self.assertEqual(IOPRIO_CLASS_NONE, 0)
self.assertEqual(IOPRIO_CLASS_RT, 1)
self.assertEqual(IOPRIO_CLASS_BE, 2)
self.assertEqual(IOPRIO_CLASS_IDLE, 3)
p = psutil.Process()
try:
p.ionice(2)
ioclass, value = p.ionice()
if enum is not None:
self.assertIsInstance(ioclass, enum.IntEnum)
self.assertEqual(ioclass, 2)
self.assertEqual(value, 4)
#
p.ionice(3)
ioclass, value = p.ionice()
self.assertEqual(ioclass, 3)
self.assertEqual(value, 0)
#
p.ionice(2, 0)
ioclass, value = p.ionice()
self.assertEqual(ioclass, 2)
self.assertEqual(value, 0)
p.ionice(2, 7)
ioclass, value = p.ionice()
self.assertEqual(ioclass, 2)
self.assertEqual(value, 7)
finally:
p.ionice(IOPRIO_CLASS_NONE)
else:
p = psutil.Process()
original = p.ionice()
self.assertIsInstance(original, int)
try:
value = 0 # very low
if original == value:
value = 1 # low
p.ionice(value)
self.assertEqual(p.ionice(), value)
finally:
p.ionice(original)
@unittest.skipIf(not HAS_IONICE, "not supported")
@unittest.skipIf(WINDOWS and get_winver() < WIN_VISTA, 'not supported')
def test_ionice_errs(self):
sproc = get_test_subprocess()
p = psutil.Process(sproc.pid)
if LINUX:
self.assertRaises(ValueError, p.ionice, 2, 10)
self.assertRaises(ValueError, p.ionice, 2, -1)
self.assertRaises(ValueError, p.ionice, 4)
self.assertRaises(TypeError, p.ionice, 2, "foo")
@unittest.skipIf(not LINUX, "linux only")
def test_ionice_linux(self):
p = psutil.Process()
self.assertEqual(p.ionice()[0], psutil.IOPRIO_CLASS_NONE)
self.assertEqual(psutil.IOPRIO_CLASS_NONE, 0)
self.assertEqual(psutil.IOPRIO_CLASS_RT, 1) # high
self.assertEqual(psutil.IOPRIO_CLASS_BE, 2) # normal
self.assertEqual(psutil.IOPRIO_CLASS_IDLE, 3) # low
try:
# low
p.ionice(psutil.IOPRIO_CLASS_IDLE)
self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_IDLE, 0))
with self.assertRaises(ValueError): # accepts no value
p.ionice(psutil.IOPRIO_CLASS_IDLE, value=7)
# normal
p.ionice(psutil.IOPRIO_CLASS_BE)
self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 0))
p.ionice(psutil.IOPRIO_CLASS_BE, value=7)
self.assertEqual(tuple(p.ionice()), (psutil.IOPRIO_CLASS_BE, 7))
with self.assertRaises(ValueError):
p.ionice(psutil.IOPRIO_CLASS_BE, value=8)
# high
if os.getuid() == 0: # root
p.ionice(psutil.IOPRIO_CLASS_RT)
self.assertEqual(tuple(p.ionice()),
(psutil.IOPRIO_CLASS_RT, 0))
p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
self.assertEqual(tuple(p.ionice()),
(psutil.IOPRIO_CLASS_RT, 7))
with self.assertRaises(ValueError):
p.ionice(psutil.IOPRIO_CLASS_IDLE, value=8)
# errs
self.assertRaisesRegex(
ValueError, "can't specify value with IOPRIO_CLASS_NONE",
ValueError, "ioclass accepts no value",
p.ionice, psutil.IOPRIO_CLASS_NONE, 1)
self.assertRaisesRegex(
ValueError, "can't specify value with IOPRIO_CLASS_IDLE",
ValueError, "ioclass accepts no value",
p.ionice, psutil.IOPRIO_CLASS_IDLE, 1)
self.assertRaisesRegex(
ValueError, "'ioclass' argument must be specified",
p.ionice, value=1)
else:
self.assertRaises(ValueError, p.ionice, 3)
self.assertRaises(TypeError, p.ionice, 2, 1)
finally:
p.ionice(psutil.IOPRIO_CLASS_BE)
@unittest.skipIf(not HAS_IONICE, "not supported")
@unittest.skipIf(not WINDOWS, 'not supported on this win version')
def test_ionice_win(self):
p = psutil.Process()
self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL)
try:
# base
p.ionice(psutil.IOPRIO_VERYLOW)
self.assertEqual(p.ionice(), psutil.IOPRIO_VERYLOW)
p.ionice(psutil.IOPRIO_LOW)
self.assertEqual(p.ionice(), psutil.IOPRIO_LOW)
try:
p.ionice(psutil.IOPRIO_HIGH)
except psutil.AccessDenied:
pass
else:
self.assertEqual(p.ionice(), psutil.IOPRIO_HIGH)
# errs
self.assertRaisesRegex(
TypeError, "value argument not accepted on Windows",
p.ionice, psutil.IOPRIO_NORMAL, value=1)
self.assertRaisesRegex(
ValueError, "is not a valid priority",
p.ionice, psutil.IOPRIO_HIGH + 1)
finally:
p.ionice(psutil.IOPRIO_NORMAL)
self.assertEqual(p.ionice(), psutil.IOPRIO_NORMAL)
@unittest.skipIf(not HAS_RLIMIT, "not supported")
def test_rlimit_get(self):
@ -508,7 +508,7 @@ class TestProcess(unittest.TestCase):
def test_num_threads(self):
# on certain platforms such as Linux we might test for exact
# thread number, since we always have with 1 thread per process,
# but this does not apply across all platforms (OSX, Windows)
# but this does not apply across all platforms (MACOS, Windows)
p = psutil.Process()
if OPENBSD:
try:
@ -542,17 +542,14 @@ class TestProcess(unittest.TestCase):
with ThreadTask():
step2 = p.threads()
self.assertEqual(len(step2), len(step1) + 1)
# on Linux, first thread id is supposed to be this process
if LINUX:
self.assertEqual(step2[0].id, os.getpid())
athread = step2[0]
# test named tuple
self.assertEqual(athread.id, athread[0])
self.assertEqual(athread.user_time, athread[1])
self.assertEqual(athread.system_time, athread[2])
@retry_before_failing()
@skip_on_access_denied(only_if=OSX)
@retry_on_failure()
@skip_on_access_denied(only_if=MACOS)
@unittest.skipIf(not HAS_THREADS, 'not supported')
def test_threads_2(self):
sproc = get_test_subprocess()
@ -606,8 +603,10 @@ class TestProcess(unittest.TestCase):
for name in mem._fields:
value = getattr(mem, name)
self.assertGreaterEqual(value, 0, msg=(name, value))
if name == 'vms' and OSX or LINUX:
continue
self.assertLessEqual(value, total, msg=(name, value, total))
if LINUX or WINDOWS or OSX:
if LINUX or WINDOWS or MACOS:
self.assertGreaterEqual(mem.uss, 0)
if LINUX:
self.assertGreaterEqual(mem.pss, 0)
@ -633,7 +632,7 @@ class TestProcess(unittest.TestCase):
raise
else:
# https://github.com/giampaolo/psutil/issues/759
with open('/proc/self/smaps') as f:
with open_text('/proc/self/smaps') as f:
data = f.read()
if "%s (deleted)" % nt.path not in data:
raise
@ -666,16 +665,10 @@ class TestProcess(unittest.TestCase):
def test_memory_percent(self):
p = psutil.Process()
ret = p.memory_percent()
assert 0 <= ret <= 100, ret
ret = p.memory_percent(memtype='vms')
assert 0 <= ret <= 100, ret
assert 0 <= ret <= 100, ret
p.memory_percent()
self.assertRaises(ValueError, p.memory_percent, memtype="?!?")
if LINUX or OSX or WINDOWS:
ret = p.memory_percent(memtype='uss')
assert 0 <= ret <= 100, ret
assert 0 <= ret <= 100, ret
if LINUX or MACOS or WINDOWS:
p.memory_percent(memtype='uss')
def test_is_running(self):
sproc = get_test_subprocess()
@ -709,7 +702,7 @@ class TestProcess(unittest.TestCase):
self.assertEqual(exe.replace(ver, ''),
PYTHON_EXE.replace(ver, ''))
except AssertionError:
# Tipically OSX. Really not sure what to do here.
# Tipically MACOS. Really not sure what to do here.
pass
out = sh([exe, "-c", "import os; print('hey')"])
@ -733,15 +726,34 @@ class TestProcess(unittest.TestCase):
else:
raise
@unittest.skipIf(PYPY, "broken on PYPY")
def test_long_cmdline(self):
create_exe(TESTFN)
self.addCleanup(safe_rmpath, TESTFN)
cmdline = [TESTFN] + (["0123456789"] * 20)
sproc = get_test_subprocess(cmdline)
p = psutil.Process(sproc.pid)
self.assertEqual(p.cmdline(), cmdline)
def test_name(self):
sproc = get_test_subprocess(PYTHON_EXE)
name = psutil.Process(sproc.pid).name().lower()
pyexe = os.path.basename(os.path.realpath(sys.executable)).lower()
assert pyexe.startswith(name), (pyexe, name)
@unittest.skipIf(PYPY, "unreliable on PYPY")
def test_long_name(self):
long_name = TESTFN + ("0123456789" * 2)
create_exe(long_name)
self.addCleanup(safe_rmpath, long_name)
sproc = get_test_subprocess(long_name)
p = psutil.Process(sproc.pid)
self.assertEqual(p.name(), os.path.basename(long_name))
# XXX
@unittest.skipIf(SUNOS, "broken on SUNOS")
@unittest.skipIf(AIX, "broken on AIX")
@unittest.skipIf(PYPY, "broken on PYPY")
def test_prog_w_funky_name(self):
# Test that name(), exe() and cmdline() correctly handle programs
# with funky chars such as spaces and ")", see:
@ -829,8 +841,8 @@ class TestProcess(unittest.TestCase):
self.assertEqual(
os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice())
# XXX - going back to previous nice value raises
# AccessDenied on OSX
if not OSX:
# AccessDenied on MACOS
if not MACOS:
p.nice(0)
self.assertEqual(p.nice(), 0)
except psutil.AccessDenied:
@ -908,8 +920,9 @@ class TestProcess(unittest.TestCase):
self.assertRaises(TypeError, p.cpu_affinity, 1)
p.cpu_affinity(initial)
# it should work with all iterables, not only lists
p.cpu_affinity(set(all_cpus))
p.cpu_affinity(tuple(all_cpus))
if not TRAVIS:
p.cpu_affinity(set(all_cpus))
p.cpu_affinity(tuple(all_cpus))
@unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported')
def test_cpu_affinity_errs(self):
@ -929,6 +942,8 @@ class TestProcess(unittest.TestCase):
self.addCleanup(p.cpu_affinity, initial)
# All possible CPU set combinations.
if len(initial) > 12:
initial = initial[:12] # ...otherwise it will take forever
combos = []
for l in range(0, len(initial) + 1):
for subset in itertools.combinations(initial, l):
@ -953,13 +968,12 @@ class TestProcess(unittest.TestCase):
f.flush()
# give the kernel some time to see the new file
files = call_until(p.open_files, "len(ret) != %i" % len(files))
for file in files:
if file.path == TESTFN:
if LINUX:
filenames = [os.path.normcase(x.path) for x in files]
self.assertIn(os.path.normcase(TESTFN), filenames)
if LINUX:
for file in files:
if file.path == TESTFN:
self.assertEqual(file.position, 1024)
break
else:
self.fail("no file found; files=%s" % repr(files))
for file in files:
assert os.path.isfile(file.path), file
@ -969,12 +983,12 @@ class TestProcess(unittest.TestCase):
p = psutil.Process(sproc.pid)
for x in range(100):
filenames = [x.path for x in p.open_files()]
filenames = [os.path.normcase(x.path) for x in p.open_files()]
if TESTFN in filenames:
break
time.sleep(.01)
else:
self.assertIn(TESTFN, filenames)
self.assertIn(os.path.normcase(TESTFN), filenames)
for file in filenames:
assert os.path.isfile(file), file
@ -984,14 +998,16 @@ class TestProcess(unittest.TestCase):
@unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR")
def test_open_files_2(self):
# test fd and path fields
normcase = os.path.normcase
with open(TESTFN, 'w') as fileobj:
p = psutil.Process()
for file in p.open_files():
if file.path == fileobj.name or file.fd == fileobj.fileno():
if normcase(file.path) == normcase(fileobj.name) or \
file.fd == fileobj.fileno():
break
else:
self.fail("no file found; files=%s" % repr(p.open_files()))
self.assertEqual(file.path, fileobj.name)
self.assertEqual(normcase(file.path), normcase(fileobj.name))
if WINDOWS:
self.assertEqual(file.fd, -1)
else:
@ -1054,6 +1070,14 @@ class TestProcess(unittest.TestCase):
p = psutil.Process(sproc.pid)
self.assertEqual(p.parent().pid, this_parent)
lowest_pid = psutil.pids()[0]
self.assertIsNone(psutil.Process(lowest_pid).parent())
def test_parent_multi(self):
p1, p2 = create_proc_children_pair()
self.assertEqual(p2.parent(), p1)
self.assertEqual(p1.parent(), psutil.Process())
def test_parent_disappeared(self):
# Emulate a case where the parent process disappeared.
sproc = get_test_subprocess()
@ -1062,7 +1086,16 @@ class TestProcess(unittest.TestCase):
side_effect=psutil.NoSuchProcess(0, 'foo')):
self.assertIsNone(p.parent())
@retry_on_failure()
def test_parents(self):
assert psutil.Process().parents()
p1, p2 = create_proc_children_pair()
self.assertEqual(p1.parents()[0], psutil.Process())
self.assertEqual(p2.parents()[0], p1)
self.assertEqual(p2.parents()[1], psutil.Process())
def test_children(self):
reap_children(recursive=True)
p = psutil.Process()
self.assertEqual(p.children(), [])
self.assertEqual(p.children(recursive=True), [])
@ -1108,6 +1141,19 @@ class TestProcess(unittest.TestCase):
else:
self.assertEqual(len(c), len(set(c)))
def test_parents_and_children(self):
p1, p2 = create_proc_children_pair()
me = psutil.Process()
# forward
children = me.children(recursive=True)
self.assertEqual(len(children), 2)
self.assertEqual(children[0], p1)
self.assertEqual(children[1], p2)
# backward
parents = p2.parents()
self.assertEqual(parents[0], p1)
self.assertEqual(parents[1], me)
def test_suspend_resume(self):
sproc = get_test_subprocess()
p = psutil.Process(sproc.pid)
@ -1202,13 +1248,28 @@ class TestProcess(unittest.TestCase):
p.cpu_times()
self.assertEqual(m.call_count, 2)
def test_oneshot_cache(self):
# Make sure oneshot() cache is nonglobal. Instead it's
# supposed to be bound to the Process instance, see:
# https://github.com/giampaolo/psutil/issues/1373
p1, p2 = create_proc_children_pair()
p1_ppid = p1.ppid()
p2_ppid = p2.ppid()
self.assertNotEqual(p1_ppid, p2_ppid)
with p1.oneshot():
self.assertEqual(p1.ppid(), p1_ppid)
self.assertEqual(p2.ppid(), p2_ppid)
with p2.oneshot():
self.assertEqual(p1.ppid(), p1_ppid)
self.assertEqual(p2.ppid(), p2_ppid)
def test_halfway_terminated_process(self):
# Test that NoSuchProcess exception gets raised in case the
# process dies after we create the Process object.
# Example:
# >>> proc = Process(1234)
# >>> proc = Process(1234)
# >>> time.sleep(2) # time-consuming task, process dies in meantime
# >>> proc.name()
# >>> proc.name()
# Refers to Issue #15
sproc = get_test_subprocess()
p = psutil.Process(sproc.pid)
@ -1216,9 +1277,13 @@ class TestProcess(unittest.TestCase):
p.wait()
if WINDOWS:
call_until(psutil.pids, "%s not in ret" % p.pid)
self.assertFalse(p.is_running())
# self.assertFalse(p.pid in psutil.pids(), msg="retcode = %s" %
# retcode)
assert not p.is_running()
if WINDOWS:
with self.assertRaises(psutil.NoSuchProcess):
p.send_signal(signal.CTRL_C_EVENT)
with self.assertRaises(psutil.NoSuchProcess):
p.send_signal(signal.CTRL_BREAK_EVENT)
excluded_names = ['pid', 'is_running', 'wait', 'create_time',
'oneshot', 'memory_info_ex']
@ -1262,6 +1327,16 @@ class TestProcess(unittest.TestCase):
except NotImplementedError:
pass
else:
# NtQuerySystemInformation succeeds if process is gone.
if WINDOWS and name in ('exe', 'name'):
normcase = os.path.normcase
if name == 'exe':
self.assertEqual(normcase(ret), normcase(PYTHON_EXE))
else:
self.assertEqual(
normcase(ret),
normcase(os.path.basename(PYTHON_EXE)))
continue
self.fail(
"NoSuchProcess exception not raised for %r, retval=%s" % (
name, ret))
@ -1320,7 +1395,7 @@ class TestProcess(unittest.TestCase):
succeed_or_zombie_p_exc(zproc.kill)
# ...its parent should 'see' it
# edit: not true on BSD and OSX
# edit: not true on BSD and MACOS
# descendants = [x.pid for x in psutil.Process().children(
# recursive=True)]
# self.assertIn(zpid, descendants)
@ -1330,9 +1405,9 @@ class TestProcess(unittest.TestCase):
# self.assertEqual(zpid.ppid(), os.getpid())
# ...and all other APIs should be able to deal with it
self.assertTrue(psutil.pid_exists(zpid))
if not TRAVIS and OSX:
if not TRAVIS and MACOS:
# For some reason this started failing all of the sudden.
# Maybe they upgraded OSX version?
# Maybe they upgraded MACOS version?
# https://travis-ci.org/giampaolo/psutil/jobs/310896404
self.assertIn(zpid, psutil.pids())
self.assertIn(zpid, [x.pid for x in psutil.process_iter()])
@ -1405,12 +1480,14 @@ class TestProcess(unittest.TestCase):
d.pop("PSUTIL_TESTING", None)
d.pop("PLAT", None)
d.pop("HOME", None)
if OSX:
if MACOS:
d.pop("__CF_USER_TEXT_ENCODING", None)
d.pop("VERSIONER_PYTHON_PREFER_32_BIT", None)
d.pop("VERSIONER_PYTHON_VERSION", None)
return dict(
[(k.rstrip("\r\n"), v.rstrip("\r\n")) for k, v in d.items()])
[(k.replace("\r", "").replace("\n", ""),
v.replace("\r", "").replace("\n", ""))
for k, v in d.items()])
self.maxDiff = None
p = psutil.Process()
@ -1562,4 +1639,5 @@ class TestPopen(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -10,7 +10,6 @@ import os
import psutil
from psutil import SUNOS
from psutil.tests import run_test_module_by_name
from psutil.tests import sh
from psutil.tests import unittest
@ -42,4 +41,5 @@ class SunOSSpecificTestCase(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@ -23,28 +23,31 @@ from psutil import AIX
from psutil import BSD
from psutil import FREEBSD
from psutil import LINUX
from psutil import MACOS
from psutil import NETBSD
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import SUNOS
from psutil import WINDOWS
from psutil._compat import FileNotFoundError
from psutil._compat import long
from psutil.tests import APPVEYOR
from psutil.tests import ASCII_FS
from psutil.tests import check_net_address
from psutil.tests import CI_TESTING
from psutil.tests import DEVNULL
from psutil.tests import enum
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_BATTERY
from psutil.tests import HAS_CPU_FREQ
from psutil.tests import HAS_GETLOADAVG
from psutil.tests import HAS_NET_IO_COUNTERS
from psutil.tests import HAS_SENSORS_BATTERY
from psutil.tests import HAS_SENSORS_FANS
from psutil.tests import HAS_SENSORS_TEMPERATURES
from psutil.tests import mock
from psutil.tests import PYPY
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import safe_rmpath
from psutil.tests import TESTFN
from psutil.tests import TESTFN_UNICODE
@ -57,8 +60,7 @@ from psutil.tests import unittest
# ===================================================================
class TestSystemAPIs(unittest.TestCase):
"""Tests for system-related APIs."""
class TestProcessAPIs(unittest.TestCase):
def setUp(self):
safe_rmpath(TESTFN)
@ -83,7 +85,7 @@ class TestSystemAPIs(unittest.TestCase):
with self.assertRaises(psutil.AccessDenied):
list(psutil.process_iter())
def test_prcess_iter_w_params(self):
def test_prcess_iter_w_attrs(self):
for p in psutil.process_iter(attrs=['pid']):
self.assertEqual(list(p.info.keys()), ['pid'])
with self.assertRaises(ValueError):
@ -103,6 +105,8 @@ class TestSystemAPIs(unittest.TestCase):
self.assertGreaterEqual(p.info['pid'], 0)
assert m.called
@unittest.skipIf(PYPY and WINDOWS,
"get_test_subprocess() unreliable on PYPY + WINDOWS")
def test_wait_procs(self):
def callback(p):
pids.append(p.pid)
@ -124,7 +128,7 @@ class TestSystemAPIs(unittest.TestCase):
for p in alive:
self.assertFalse(hasattr(p, 'returncode'))
@retry_before_failing(30)
@retry_on_failure(30)
def test(procs, callback):
gone, alive = psutil.wait_procs(procs, timeout=0.03,
callback=callback)
@ -143,7 +147,7 @@ class TestSystemAPIs(unittest.TestCase):
for p in alive:
self.assertFalse(hasattr(p, 'returncode'))
@retry_before_failing(30)
@retry_on_failure(30)
def test(procs, callback):
gone, alive = psutil.wait_procs(procs, timeout=0.03,
callback=callback)
@ -158,6 +162,8 @@ class TestSystemAPIs(unittest.TestCase):
for p in gone:
self.assertTrue(hasattr(p, 'returncode'))
@unittest.skipIf(PYPY and WINDOWS,
"get_test_subprocess() unreliable on PYPY + WINDOWS")
def test_wait_procs_no_timeout(self):
sproc1 = get_test_subprocess()
sproc2 = get_test_subprocess()
@ -167,12 +173,67 @@ class TestSystemAPIs(unittest.TestCase):
p.terminate()
gone, alive = psutil.wait_procs(procs)
def test_pid_exists(self):
sproc = get_test_subprocess()
self.assertTrue(psutil.pid_exists(sproc.pid))
p = psutil.Process(sproc.pid)
p.kill()
p.wait()
self.assertFalse(psutil.pid_exists(sproc.pid))
self.assertFalse(psutil.pid_exists(-1))
self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids())
def test_pid_exists_2(self):
reap_children()
pids = psutil.pids()
for pid in pids:
try:
assert psutil.pid_exists(pid)
except AssertionError:
# in case the process disappeared in meantime fail only
# if it is no longer in psutil.pids()
time.sleep(.1)
if pid in psutil.pids():
self.fail(pid)
pids = range(max(pids) + 5000, max(pids) + 6000)
for pid in pids:
self.assertFalse(psutil.pid_exists(pid), msg=pid)
def test_pids(self):
pidslist = psutil.pids()
procslist = [x.pid for x in psutil.process_iter()]
# make sure every pid is unique
self.assertEqual(sorted(set(pidslist)), pidslist)
self.assertEqual(pidslist, procslist)
class TestMiscAPIs(unittest.TestCase):
def test_boot_time(self):
bt = psutil.boot_time()
self.assertIsInstance(bt, float)
self.assertGreater(bt, 0)
self.assertLess(bt, time.time())
@unittest.skipIf(CI_TESTING and not psutil.users(), "unreliable on CI")
def test_users(self):
users = psutil.users()
self.assertNotEqual(users, [])
for user in users:
assert user.name, user
self.assertIsInstance(user.name, str)
self.assertIsInstance(user.terminal, (str, type(None)))
if user.host is not None:
self.assertIsInstance(user.host, (str, type(None)))
user.terminal
user.host
assert user.started > 0.0, user
datetime.datetime.fromtimestamp(user.started)
if WINDOWS or OPENBSD:
self.assertIsNone(user.pid)
else:
psutil.Process(user.pid)
@unittest.skipIf(not POSIX, 'POSIX only')
def test_PAGESIZE(self):
# pagesize is used internally to perform different calculations
@ -181,6 +242,55 @@ class TestSystemAPIs(unittest.TestCase):
import resource
self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize())
def test_test(self):
# test for psutil.test() function
stdout = sys.stdout
sys.stdout = DEVNULL
try:
psutil.test()
finally:
sys.stdout = stdout
def test_os_constants(self):
names = ["POSIX", "WINDOWS", "LINUX", "MACOS", "FREEBSD", "OPENBSD",
"NETBSD", "BSD", "SUNOS"]
for name in names:
self.assertIsInstance(getattr(psutil, name), bool, msg=name)
if os.name == 'posix':
assert psutil.POSIX
assert not psutil.WINDOWS
names.remove("POSIX")
if "linux" in sys.platform.lower():
assert psutil.LINUX
names.remove("LINUX")
elif "bsd" in sys.platform.lower():
assert psutil.BSD
self.assertEqual([psutil.FREEBSD, psutil.OPENBSD,
psutil.NETBSD].count(True), 1)
names.remove("BSD")
names.remove("FREEBSD")
names.remove("OPENBSD")
names.remove("NETBSD")
elif "sunos" in sys.platform.lower() or \
"solaris" in sys.platform.lower():
assert psutil.SUNOS
names.remove("SUNOS")
elif "darwin" in sys.platform.lower():
assert psutil.MACOS
names.remove("MACOS")
else:
assert psutil.WINDOWS
assert not psutil.POSIX
names.remove("WINDOWS")
# assert all other constants are set to False
for name in names:
self.assertIs(getattr(psutil, name), False, msg=name)
class TestMemoryAPIs(unittest.TestCase):
def test_virtual_memory(self):
mem = psutil.virtual_memory()
assert mem.total > 0, mem
@ -215,50 +325,12 @@ class TestSystemAPIs(unittest.TestCase):
assert mem.sin >= 0, mem
assert mem.sout >= 0, mem
def test_pid_exists(self):
sproc = get_test_subprocess()
self.assertTrue(psutil.pid_exists(sproc.pid))
p = psutil.Process(sproc.pid)
p.kill()
p.wait()
self.assertFalse(psutil.pid_exists(sproc.pid))
self.assertFalse(psutil.pid_exists(-1))
self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids())
def test_pid_exists_2(self):
reap_children()
pids = psutil.pids()
for pid in pids:
try:
assert psutil.pid_exists(pid)
except AssertionError:
# in case the process disappeared in meantime fail only
# if it is no longer in psutil.pids()
time.sleep(.1)
if pid in psutil.pids():
self.fail(pid)
pids = range(max(pids) + 5000, max(pids) + 6000)
for pid in pids:
self.assertFalse(psutil.pid_exists(pid), msg=pid)
class TestCpuAPIs(unittest.TestCase):
def test_pids(self):
plist = [x.pid for x in psutil.process_iter()]
pidlist = psutil.pids()
self.assertEqual(plist.sort(), pidlist.sort())
# make sure every pid is unique
self.assertEqual(len(pidlist), len(set(pidlist)))
def test_test(self):
# test for psutil.test() function
stdout = sys.stdout
sys.stdout = DEVNULL
try:
psutil.test()
finally:
sys.stdout = stdout
def test_cpu_count(self):
def test_cpu_count_logical(self):
logical = psutil.cpu_count()
self.assertIsNotNone(logical)
self.assertEqual(logical, len(psutil.cpu_times(percpu=True)))
self.assertGreaterEqual(logical, 1)
#
@ -267,9 +339,17 @@ class TestSystemAPIs(unittest.TestCase):
cpuinfo_data = fd.read()
if "physical id" not in cpuinfo_data:
raise unittest.SkipTest("cpuinfo doesn't include physical id")
def test_cpu_count_physical(self):
logical = psutil.cpu_count()
physical = psutil.cpu_count(logical=False)
self.assertGreaterEqual(physical, 1)
self.assertGreaterEqual(logical, physical)
if physical is None:
raise self.skipTest("physical cpu_count() is None")
if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista
self.assertIsNone(physical)
else:
self.assertGreaterEqual(physical, 1)
self.assertGreaterEqual(logical, physical)
def test_cpu_count_none(self):
# https://github.com/giampaolo/psutil/issues/1085
@ -315,11 +395,12 @@ class TestSystemAPIs(unittest.TestCase):
def test_cpu_times_time_increases(self):
# Make sure time increases between calls.
t1 = sum(psutil.cpu_times())
time.sleep(0.1)
t2 = sum(psutil.cpu_times())
difference = t2 - t1
if not difference >= 0.05:
self.fail("difference %s" % difference)
stop_at = time.time() + 1
while time.time() < stop_at:
t2 = sum(psutil.cpu_times())
if t2 > t1:
return
self.fail("time remained the same")
def test_per_cpu_times(self):
# Check type, value >= 0, str().
@ -358,17 +439,16 @@ class TestSystemAPIs(unittest.TestCase):
# Simulate some work load then make sure time have increased
# between calls.
tot1 = psutil.cpu_times(percpu=True)
stop_at = time.time() + 0.1
giveup_at = time.time() + 1
while True:
if time.time() >= stop_at:
break
tot2 = psutil.cpu_times(percpu=True)
for t1, t2 in zip(tot1, tot2):
t1, t2 = sum(t1), sum(t2)
difference = t2 - t1
if difference >= 0.05:
return
self.fail()
if time.time() >= giveup_at:
return self.fail("timeout")
tot2 = psutil.cpu_times(percpu=True)
for t1, t2 in zip(tot1, tot2):
t1, t2 = psutil._cpu_busy_time(t1), psutil._cpu_busy_time(t2)
difference = t2 - t1
if difference >= 0.05:
return
def test_cpu_times_comparison(self):
# Make sure the sum of all per cpu times is almost equal to
@ -440,6 +520,55 @@ class TestSystemAPIs(unittest.TestCase):
for percent in cpu:
self._test_cpu_percent(percent, None, None)
def test_cpu_stats(self):
# Tested more extensively in per-platform test modules.
infos = psutil.cpu_stats()
self.assertEqual(
infos._fields,
('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'))
for name in infos._fields:
value = getattr(infos, name)
self.assertGreaterEqual(value, 0)
# on AIX, ctx_switches is always 0
if not AIX and name in ('ctx_switches', 'interrupts'):
self.assertGreater(value, 0)
@unittest.skipIf(not HAS_CPU_FREQ, "not suported")
def test_cpu_freq(self):
def check_ls(ls):
for nt in ls:
self.assertEqual(nt._fields, ('current', 'min', 'max'))
if nt.max != 0.0:
self.assertLessEqual(nt.current, nt.max)
for name in nt._fields:
value = getattr(nt, name)
self.assertIsInstance(value, (int, long, float))
self.assertGreaterEqual(value, 0)
ls = psutil.cpu_freq(percpu=True)
if TRAVIS and not ls:
raise self.skipTest("skipped on Travis")
if FREEBSD and not ls:
raise self.skipTest("returns empty list on FreeBSD")
assert ls, ls
check_ls([psutil.cpu_freq(percpu=False)])
if LINUX:
self.assertEqual(len(ls), psutil.cpu_count())
@unittest.skipIf(not HAS_GETLOADAVG, "not supported")
def test_getloadavg(self):
loadavg = psutil.getloadavg()
assert len(loadavg) == 3
for load in loadavg:
self.assertIsInstance(load, float)
self.assertGreaterEqual(load, 0.0)
class TestDiskAPIs(unittest.TestCase):
def test_disk_usage(self):
usage = psutil.disk_usage(os.getcwd())
self.assertEqual(usage._fields, ('total', 'used', 'free', 'percent'))
@ -463,9 +592,8 @@ class TestSystemAPIs(unittest.TestCase):
# if path does not exist OSError ENOENT is expected across
# all platforms
fname = tempfile.mktemp()
with self.assertRaises(OSError) as exc:
with self.assertRaises(FileNotFoundError):
psutil.disk_usage(fname)
self.assertEqual(exc.exception.errno, errno.ENOENT)
def test_disk_usage_unicode(self):
# See: https://github.com/giampaolo/psutil/issues/416
@ -496,33 +624,26 @@ class TestSystemAPIs(unittest.TestCase):
# we cannot make any assumption about this, see:
# http://goo.gl/p9c43
disk.device
if SUNOS or TRAVIS:
# on solaris apparently mount points can also be files
assert os.path.exists(disk.mountpoint), disk
else:
assert os.path.isdir(disk.mountpoint), disk
# on modern systems mount points can also be files
assert os.path.exists(disk.mountpoint), disk
assert disk.fstype, disk
# all = True
ls = psutil.disk_partitions(all=True)
self.assertTrue(ls, msg=ls)
for disk in psutil.disk_partitions(all=True):
if not WINDOWS:
if not WINDOWS and disk.mountpoint:
try:
os.stat(disk.mountpoint)
except OSError as err:
if TRAVIS and OSX and err.errno == errno.EIO:
if TRAVIS and MACOS and err.errno == errno.EIO:
continue
# http://mail.python.org/pipermail/python-dev/
# 2012-June/120787.html
if err.errno not in (errno.EPERM, errno.EACCES):
raise
else:
if SUNOS or TRAVIS:
# on solaris apparently mount points can also be files
assert os.path.exists(disk.mountpoint), disk
else:
assert os.path.isdir(disk.mountpoint), disk
assert os.path.exists(disk.mountpoint), disk
self.assertIsInstance(disk.fstype, str)
self.assertIsInstance(disk.opts, str)
@ -534,10 +655,55 @@ class TestSystemAPIs(unittest.TestCase):
mount = find_mount_point(__file__)
mounts = [x.mountpoint.lower() for x in
psutil.disk_partitions(all=True)]
psutil.disk_partitions(all=True) if x.mountpoint]
self.assertIn(mount, mounts)
psutil.disk_usage(mount)
@unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
'/proc/diskstats not available on this linux version')
@unittest.skipIf(CI_TESTING and not psutil.disk_io_counters(),
"unreliable on CI") # no visible disks
def test_disk_io_counters(self):
def check_ntuple(nt):
self.assertEqual(nt[0], nt.read_count)
self.assertEqual(nt[1], nt.write_count)
self.assertEqual(nt[2], nt.read_bytes)
self.assertEqual(nt[3], nt.write_bytes)
if not (OPENBSD or NETBSD):
self.assertEqual(nt[4], nt.read_time)
self.assertEqual(nt[5], nt.write_time)
if LINUX:
self.assertEqual(nt[6], nt.read_merged_count)
self.assertEqual(nt[7], nt.write_merged_count)
self.assertEqual(nt[8], nt.busy_time)
elif FREEBSD:
self.assertEqual(nt[6], nt.busy_time)
for name in nt._fields:
assert getattr(nt, name) >= 0, nt
ret = psutil.disk_io_counters(perdisk=False)
assert ret is not None, "no disks on this system?"
check_ntuple(ret)
ret = psutil.disk_io_counters(perdisk=True)
# make sure there are no duplicates
self.assertEqual(len(ret), len(set(ret)))
for key in ret:
assert key, key
check_ntuple(ret[key])
def test_disk_io_counters_no_disks(self):
# Emulate a case where no disks are installed, see:
# https://github.com/giampaolo/psutil/issues/1062
with mock.patch('psutil._psplatform.disk_io_counters',
return_value={}) as m:
self.assertIsNone(psutil.disk_io_counters(perdisk=False))
self.assertEqual(psutil.disk_io_counters(perdisk=True), {})
assert m.called
class TestNetAPIs(unittest.TestCase):
@unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
def test_net_io_counters(self):
def check_ntuple(nt):
self.assertEqual(nt[0], nt.bytes_sent)
@ -566,6 +732,7 @@ class TestSystemAPIs(unittest.TestCase):
self.assertIsInstance(key, str)
check_ntuple(ret[key])
@unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported')
def test_net_io_counters_no_nics(self):
# Emulate a case where no NICs are installed, see:
# https://github.com/giampaolo/psutil/issues/1062
@ -627,7 +794,7 @@ class TestSystemAPIs(unittest.TestCase):
elif addr.ptp:
self.assertIsNone(addr.broadcast)
if BSD or OSX or SUNOS:
if BSD or MACOS or SUNOS:
if hasattr(socket, "AF_LINK"):
self.assertEqual(psutil.AF_LINK, socket.AF_LINK)
elif LINUX:
@ -668,144 +835,18 @@ class TestSystemAPIs(unittest.TestCase):
self.assertGreaterEqual(speed, 0)
self.assertGreaterEqual(mtu, 0)
@unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
'/proc/diskstats not available on this linux version')
@unittest.skipIf(APPVEYOR and psutil.disk_io_counters() is None,
"unreliable on APPVEYOR") # no visible disks
def test_disk_io_counters(self):
def check_ntuple(nt):
self.assertEqual(nt[0], nt.read_count)
self.assertEqual(nt[1], nt.write_count)
self.assertEqual(nt[2], nt.read_bytes)
self.assertEqual(nt[3], nt.write_bytes)
if not (OPENBSD or NETBSD):
self.assertEqual(nt[4], nt.read_time)
self.assertEqual(nt[5], nt.write_time)
if LINUX:
self.assertEqual(nt[6], nt.read_merged_count)
self.assertEqual(nt[7], nt.write_merged_count)
self.assertEqual(nt[8], nt.busy_time)
elif FREEBSD:
self.assertEqual(nt[6], nt.busy_time)
for name in nt._fields:
assert getattr(nt, name) >= 0, nt
ret = psutil.disk_io_counters(perdisk=False)
assert ret is not None, "no disks on this system?"
check_ntuple(ret)
ret = psutil.disk_io_counters(perdisk=True)
# make sure there are no duplicates
self.assertEqual(len(ret), len(set(ret)))
for key in ret:
assert key, key
check_ntuple(ret[key])
if LINUX and key[-1].isdigit():
# if 'sda1' is listed 'sda' shouldn't, see:
# https://github.com/giampaolo/psutil/issues/338
while key[-1].isdigit():
key = key[:-1]
self.assertNotIn(key, ret.keys())
def test_disk_io_counters_no_disks(self):
# Emulate a case where no disks are installed, see:
# https://github.com/giampaolo/psutil/issues/1062
with mock.patch('psutil._psplatform.disk_io_counters',
return_value={}) as m:
self.assertIsNone(psutil.disk_io_counters(perdisk=False))
self.assertEqual(psutil.disk_io_counters(perdisk=True), {})
@unittest.skipIf(not (LINUX or BSD or MACOS),
"LINUX or BSD or MACOS specific")
def test_net_if_stats_enodev(self):
# See: https://github.com/giampaolo/psutil/issues/1279
with mock.patch('psutil._psutil_posix.net_if_mtu',
side_effect=OSError(errno.ENODEV, "")) as m:
ret = psutil.net_if_stats()
self.assertEqual(ret, {})
assert m.called
# can't find users on APPVEYOR or TRAVIS
@unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(),
"unreliable on APPVEYOR or TRAVIS")
def test_users(self):
users = psutil.users()
self.assertNotEqual(users, [])
for user in users:
assert user.name, user
self.assertIsInstance(user.name, str)
self.assertIsInstance(user.terminal, (str, type(None)))
if user.host is not None:
self.assertIsInstance(user.host, (str, type(None)))
user.terminal
user.host
assert user.started > 0.0, user
datetime.datetime.fromtimestamp(user.started)
if WINDOWS or OPENBSD:
self.assertIsNone(user.pid)
else:
psutil.Process(user.pid)
def test_cpu_stats(self):
# Tested more extensively in per-platform test modules.
infos = psutil.cpu_stats()
self.assertEqual(
infos._fields,
('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls'))
for name in infos._fields:
value = getattr(infos, name)
self.assertGreaterEqual(value, 0)
# on AIX, ctx_switches is always 0
if not AIX and name in ('ctx_switches', 'interrupts'):
self.assertGreater(value, 0)
@unittest.skipIf(not HAS_CPU_FREQ, "not suported")
def test_cpu_freq(self):
def check_ls(ls):
for nt in ls:
self.assertEqual(nt._fields, ('current', 'min', 'max'))
self.assertLessEqual(nt.current, nt.max)
for name in nt._fields:
value = getattr(nt, name)
self.assertIsInstance(value, (int, long, float))
self.assertGreaterEqual(value, 0)
ls = psutil.cpu_freq(percpu=True)
if TRAVIS and not ls:
return
assert ls, ls
check_ls([psutil.cpu_freq(percpu=False)])
if LINUX:
self.assertEqual(len(ls), psutil.cpu_count())
def test_os_constants(self):
names = ["POSIX", "WINDOWS", "LINUX", "OSX", "FREEBSD", "OPENBSD",
"NETBSD", "BSD", "SUNOS"]
for name in names:
self.assertIsInstance(getattr(psutil, name), bool, msg=name)
if os.name == 'posix':
assert psutil.POSIX
assert not psutil.WINDOWS
names.remove("POSIX")
if "linux" in sys.platform.lower():
assert psutil.LINUX
names.remove("LINUX")
elif "bsd" in sys.platform.lower():
assert psutil.BSD
self.assertEqual([psutil.FREEBSD, psutil.OPENBSD,
psutil.NETBSD].count(True), 1)
names.remove("BSD")
names.remove("FREEBSD")
names.remove("OPENBSD")
names.remove("NETBSD")
elif "sunos" in sys.platform.lower() or \
"solaris" in sys.platform.lower():
assert psutil.SUNOS
names.remove("SUNOS")
elif "darwin" in sys.platform.lower():
assert psutil.OSX
names.remove("OSX")
else:
assert psutil.WINDOWS
assert not psutil.POSIX
names.remove("WINDOWS")
# assert all other constants are set to False
for name in names:
self.assertIs(getattr(psutil, name), False, msg=name)
class TestSensorsAPIs(unittest.TestCase):
@unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported")
def test_sensors_temperatures(self):
@ -859,4 +900,5 @@ class TestSystemAPIs(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
@ -9,7 +9,32 @@
Notes about unicode handling in psutil
======================================
In psutil these are the APIs returning or dealing with a string
Starting from version 5.3.0 psutil adds unicode support, see:
https://github.com/giampaolo/psutil/issues/1040
The notes below apply to *any* API returning a string such as
process exe(), cwd() or username():
* all strings are encoded by using the OS filesystem encoding
(sys.getfilesystemencoding()) which varies depending on the platform
(e.g. "UTF-8" on macOS, "mbcs" on Win)
* no API call is supposed to crash with UnicodeDecodeError
* instead, in case of badly encoded data returned by the OS, the
following error handlers are used to replace the corrupted characters in
the string:
* Python 3: sys.getfilesystemencodeerrors() (PY 3.6+) or
"surrogatescape" on POSIX and "replace" on Windows
* Python 2: "replace"
* on Python 2 all APIs return bytes (str type), never unicode
* on Python 2, you can go back to unicode by doing:
>>> unicode(p.exe(), sys.getdefaultencoding(), errors="replace")
For a detailed explanation of how psutil handles unicode see #1040.
Tests
=====
List of APIs returning or dealing with a string:
('not tested' means they are not tested to deal with non-ASCII strings):
* Process.cmdline()
@ -46,10 +71,6 @@ etc.) and make sure that:
* psutil never crashes with UnicodeDecodeError
* the returned path matches
For a detailed explanation of how psutil handles unicode see:
- https://github.com/giampaolo/psutil/issues/1040
- http://psutil.readthedocs.io/#unicode
"""
import os
@ -58,13 +79,14 @@ import warnings
from contextlib import closing
from psutil import BSD
from psutil import MACOS
from psutil import OPENBSD
from psutil import OSX
from psutil import POSIX
from psutil import WINDOWS
from psutil._compat import PY3
from psutil._compat import u
from psutil.tests import APPVEYOR
from psutil.tests import CIRRUS
from psutil.tests import ASCII_FS
from psutil.tests import bind_unix_socket
from psutil.tests import chdir
@ -74,9 +96,8 @@ from psutil.tests import get_test_subprocess
from psutil.tests import HAS_CONNECTIONS_UNIX
from psutil.tests import HAS_ENVIRON
from psutil.tests import HAS_MEMORY_MAPS
from psutil.tests import mock
from psutil.tests import PYPY
from psutil.tests import reap_children
from psutil.tests import run_test_module_by_name
from psutil.tests import safe_mkdir
from psutil.tests import safe_rmpath as _safe_rmpath
from psutil.tests import skip_on_access_denied
@ -87,7 +108,6 @@ from psutil.tests import TRAVIS
from psutil.tests import unittest
from psutil.tests import unix_socket_path
import psutil
import psutil.tests
def safe_rmpath(path):
@ -166,20 +186,12 @@ class _BaseFSAPIsTests(object):
exe = p.exe()
self.assertIsInstance(exe, str)
if self.expect_exact_path_match():
self.assertEqual(exe, self.funky_name)
self.assertEqual(os.path.normcase(exe),
os.path.normcase(self.funky_name))
def test_proc_name(self):
subp = get_test_subprocess(cmd=[self.funky_name])
if WINDOWS:
# On Windows name() is determined from exe() first, because
# it's faster; we want to overcome the internal optimization
# and test name() instead of exe().
with mock.patch("psutil._psplatform.cext.proc_exe",
side_effect=psutil.AccessDenied(os.getpid())) as m:
name = psutil.Process(subp.pid).name()
assert m.called
else:
name = psutil.Process(subp.pid).name()
name = psutil.Process(subp.pid).name()
self.assertIsInstance(name, str)
if self.expect_exact_path_match():
self.assertEqual(name, os.path.basename(self.funky_name))
@ -204,6 +216,7 @@ class _BaseFSAPIsTests(object):
if self.expect_exact_path_match():
self.assertEqual(cwd, dname)
@unittest.skipIf(PYPY and WINDOWS, "fails on PYPY + WINDOWS")
def test_proc_open_files(self):
p = psutil.Process()
start = set(p.open_files())
@ -233,7 +246,7 @@ class _BaseFSAPIsTests(object):
conn = psutil.Process().connections('unix')[0]
self.assertIsInstance(conn.laddr, str)
# AF_UNIX addr not set on OpenBSD
if not OPENBSD:
if not OPENBSD and not CIRRUS: # XXX
self.assertEqual(conn.laddr, name)
@unittest.skipIf(not POSIX, "POSIX only")
@ -271,6 +284,8 @@ class _BaseFSAPIsTests(object):
@unittest.skipIf(not HAS_MEMORY_MAPS, "not supported")
@unittest.skipIf(not PY3, "ctypes does not support unicode on PY2")
@unittest.skipIf(PYPY and WINDOWS,
"copyload_shared_lib() unsupported on PYPY + WINDOWS")
def test_memory_maps(self):
# XXX: on Python 2, using ctypes.CDLL with a unicode path
# opens a message box which blocks the test run.
@ -286,7 +301,9 @@ class _BaseFSAPIsTests(object):
self.assertIsInstance(path, str)
@unittest.skipIf(OSX and TRAVIS, "unreliable on TRAVIS") # TODO
# https://travis-ci.org/giampaolo/psutil/jobs/440073249
@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS")
@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO
@unittest.skipIf(ASCII_FS, "ASCII fs")
@unittest.skipIf(not subprocess_supports_unicode(TESTFN_UNICODE),
"subprocess can't deal with unicode")
@ -298,16 +315,15 @@ class TestFSAPIs(_BaseFSAPIsTests, unittest.TestCase):
def expect_exact_path_match(cls):
# Do not expect psutil to correctly handle unicode paths on
# Python 2 if os.listdir() is not able either.
if PY3:
return True
else:
here = '.' if isinstance(cls.funky_name, str) else u('.')
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return cls.funky_name in os.listdir(here)
here = '.' if isinstance(cls.funky_name, str) else u('.')
with warnings.catch_warnings():
warnings.simplefilter("ignore")
return cls.funky_name in os.listdir(here)
@unittest.skipIf(OSX and TRAVIS, "unreliable on TRAVIS") # TODO
@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS")
@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO
@unittest.skipIf(PYPY, "unreliable on PYPY")
@unittest.skipIf(not subprocess_supports_unicode(INVALID_NAME),
"subprocess can't deal with invalid unicode")
class TestFSAPIsWithInvalidPath(_BaseFSAPIsTests, unittest.TestCase):
@ -320,19 +336,6 @@ class TestFSAPIsWithInvalidPath(_BaseFSAPIsTests, unittest.TestCase):
return True
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestWinProcessName(unittest.TestCase):
def test_name_type(self):
# On Windows name() is determined from exe() first, because
# it's faster; we want to overcome the internal optimization
# and test name() instead of exe().
with mock.patch("psutil._psplatform.cext.proc_exe",
side_effect=psutil.AccessDenied(os.getpid())) as m:
self.assertIsInstance(psutil.Process().name(), str)
assert m.called
# ===================================================================
# Non fs APIs
# ===================================================================
@ -345,6 +348,7 @@ class TestNonFSAPIS(unittest.TestCase):
reap_children()
@unittest.skipIf(not HAS_ENVIRON, "not supported")
@unittest.skipIf(PYPY and WINDOWS, "segfaults on PYPY + WINDOWS")
def test_proc_environ(self):
# Note: differently from others, this test does not deal
# with fs paths. On Python 2 subprocess module is broken as
@ -364,4 +368,5 @@ class TestNonFSAPIS(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

Просмотреть файл

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: UTF-8 -*
# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
@ -21,27 +21,26 @@ import warnings
import psutil
from psutil import WINDOWS
from psutil._compat import callable
from psutil._compat import FileNotFoundError
from psutil.tests import APPVEYOR
from psutil.tests import get_test_subprocess
from psutil.tests import HAS_BATTERY
from psutil.tests import mock
from psutil.tests import PY3
from psutil.tests import PYPY
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
from psutil.tests import retry_on_failure
from psutil.tests import sh
from psutil.tests import unittest
with warnings.catch_warnings():
warnings.simplefilter("ignore")
try:
if WINDOWS and not PYPY:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
import win32api # requires "pip install pypiwin32"
import win32con
import win32process
import wmi # requires "pip install wmi" / "make setup-dev-env"
except ImportError:
if os.name == 'nt':
raise
cext = psutil._psplatform.cext
@ -64,13 +63,57 @@ def wrap_exceptions(fun):
return wrapper
@unittest.skipIf(PYPY, "pywin32 not available on PYPY") # skip whole module
class TestCase(unittest.TestCase):
pass
# ===================================================================
# System APIs
# ===================================================================
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestSystemAPIs(unittest.TestCase):
class TestCpuAPIs(TestCase):
@unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ,
'NUMBER_OF_PROCESSORS env var is not available')
def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self):
# Will likely fail on many-cores systems:
# https://stackoverflow.com/questions/31209256
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
self.assertEqual(num_cpus, psutil.cpu_count())
def test_cpu_count_vs_GetSystemInfo(self):
# Will likely fail on many-cores systems:
# https://stackoverflow.com/questions/31209256
sys_value = win32api.GetSystemInfo()[5]
psutil_value = psutil.cpu_count()
self.assertEqual(sys_value, psutil_value)
def test_cpu_count_logical_vs_wmi(self):
w = wmi.WMI()
proc = w.Win32_Processor()[0]
self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors)
def test_cpu_count_phys_vs_wmi(self):
w = wmi.WMI()
proc = w.Win32_Processor()[0]
self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores)
def test_cpu_count_vs_cpu_times(self):
self.assertEqual(psutil.cpu_count(),
len(psutil.cpu_times(percpu=True)))
def test_cpu_freq(self):
w = wmi.WMI()
proc = w.Win32_Processor()[0]
self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current)
self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max)
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestSystemAPIs(TestCase):
def test_nic_names(self):
out = sh('ipconfig /all')
@ -82,23 +125,6 @@ class TestSystemAPIs(unittest.TestCase):
self.fail(
"%r nic wasn't found in 'ipconfig /all' output" % nic)
@unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ,
'NUMBER_OF_PROCESSORS env var is not available')
def test_cpu_count(self):
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
self.assertEqual(num_cpus, psutil.cpu_count())
def test_cpu_count_2(self):
sys_value = win32api.GetSystemInfo()[5]
psutil_value = psutil.cpu_count()
self.assertEqual(sys_value, psutil_value)
def test_cpu_freq(self):
w = wmi.WMI()
proc = w.Win32_Processor()[0]
self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current)
self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max)
def test_total_phymem(self):
w = wmi.WMI().Win32_ComputerSystem()[0]
self.assertEqual(int(w.TotalPhysicalMemory),
@ -117,7 +143,7 @@ class TestSystemAPIs(unittest.TestCase):
# Note: this test is not very reliable
@unittest.skipIf(APPVEYOR, "test not relieable on appveyor")
@retry_before_failing()
@retry_on_failure()
def test_pids(self):
# Note: this test might fail if the OS is starting/killing
# other processes in the meantime
@ -126,7 +152,7 @@ class TestSystemAPIs(unittest.TestCase):
psutil_pids = set(psutil.pids())
self.assertEqual(wmi_pids, psutil_pids)
@retry_before_failing()
@retry_on_failure()
def test_disks(self):
ps_parts = psutil.disk_partitions(all=True)
wmi_parts = wmi.WMI().Win32_LogicalDisk()
@ -136,14 +162,13 @@ class TestSystemAPIs(unittest.TestCase):
if not ps_part.mountpoint:
# this is usually a CD-ROM with no disk inserted
break
if 'cdrom' in ps_part.opts:
break
try:
usage = psutil.disk_usage(ps_part.mountpoint)
except OSError as err:
if err.errno == errno.ENOENT:
# usually this is the floppy
break
else:
raise
except FileNotFoundError:
# usually this is the floppy
break
self.assertEqual(usage.total, int(wmi_part.Size))
wmi_free = int(wmi_part.FreeSpace)
self.assertEqual(usage.free, wmi_free)
@ -157,6 +182,8 @@ class TestSystemAPIs(unittest.TestCase):
def test_disk_usage(self):
for disk in psutil.disk_partitions():
if 'cdrom' in disk.opts:
continue
sys_value = win32api.GetDiskFreeSpaceEx(disk.mountpoint)
psutil_value = psutil.disk_usage(disk.mountpoint)
self.assertAlmostEqual(sys_value[0], psutil_value.free,
@ -190,7 +217,6 @@ class TestSystemAPIs(unittest.TestCase):
wmi_btime_str, "%Y%m%d%H%M%S")
psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time())
diff = abs((wmi_btime_dt - psutil_dt).total_seconds())
# Wmic time is 2-3 secs lower for some reason; that's OK.
self.assertLessEqual(diff, 3)
def test_boot_time_fluctuation(self):
@ -211,7 +237,7 @@ class TestSystemAPIs(unittest.TestCase):
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestSensorsBattery(unittest.TestCase):
class TestSensorsBattery(TestCase):
def test_has_battery(self):
if win32api.GetPwrCapabilities()['SystemBatteriesPresent']:
@ -272,7 +298,7 @@ class TestSensorsBattery(unittest.TestCase):
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestProcess(unittest.TestCase):
class TestProcess(TestCase):
@classmethod
def setUpClass(cls):
@ -307,13 +333,6 @@ class TestProcess(unittest.TestCase):
p = psutil.Process(self.pid)
self.assertRaises(ValueError, p.send_signal, signal.SIGINT)
def test_exe(self):
for p in psutil.process_iter():
try:
self.assertEqual(os.path.basename(p.exe()), p.name())
except psutil.Error:
pass
def test_num_handles_increment(self):
p = psutil.Process(os.getpid())
before = p.num_handles()
@ -360,15 +379,6 @@ class TestProcess(unittest.TestCase):
if failures:
self.fail('\n' + '\n'.join(failures))
def test_name_always_available(self):
# On Windows name() is never supposed to raise AccessDenied,
# see https://github.com/giampaolo/psutil/issues/627
for p in psutil.process_iter():
try:
p.name()
except psutil.NoSuchProcess:
pass
@unittest.skipIf(not sys.version_info >= (2, 7),
"CTRL_* signals not supported")
def test_ctrl_signals(self):
@ -382,16 +392,6 @@ class TestProcess(unittest.TestCase):
self.assertRaises(psutil.NoSuchProcess,
p.send_signal, signal.CTRL_BREAK_EVENT)
def test_compare_name_exe(self):
for p in psutil.process_iter():
try:
a = os.path.basename(p.exe())
b = p.name()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
else:
self.assertEqual(a, b)
def test_username(self):
self.assertEqual(psutil.Process().username(),
win32api.GetUserNameEx(win32con.NameSamCompatible))
@ -497,19 +497,36 @@ class TestProcess(unittest.TestCase):
import ctypes.wintypes
PROCESS_QUERY_INFORMATION = 0x400
handle = ctypes.windll.kernel32.OpenProcess(
PROCESS_QUERY_INFORMATION, 0, os.getpid())
PROCESS_QUERY_INFORMATION, 0, self.pid)
self.addCleanup(ctypes.windll.kernel32.CloseHandle, handle)
hndcnt = ctypes.wintypes.DWORD()
ctypes.windll.kernel32.GetProcessHandleCount(
handle, ctypes.byref(hndcnt))
sys_value = hndcnt.value
psutil_value = psutil.Process().num_handles()
ctypes.windll.kernel32.CloseHandle(handle)
self.assertEqual(psutil_value, sys_value + 1)
psutil_value = psutil.Process(self.pid).num_handles()
self.assertEqual(psutil_value, sys_value)
def test_error_partial_copy(self):
# https://github.com/giampaolo/psutil/issues/875
exc = WindowsError()
exc.winerror = 299
with mock.patch("psutil._psplatform.cext.proc_cwd", side_effect=exc):
with mock.patch("time.sleep") as m:
p = psutil.Process()
self.assertRaises(psutil.AccessDenied, p.cwd)
self.assertGreaterEqual(m.call_count, 5)
def test_exe(self):
# NtQuerySystemInformation succeeds if process is gone. Make sure
# it raises NSP for a non existent pid.
pid = psutil.pids()[-1] + 99999
proc = psutil._psplatform.Process(pid)
self.assertRaises(psutil.NoSuchProcess, proc.exe)
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestProcessWMI(unittest.TestCase):
class TestProcessWMI(TestCase):
"""Compare Process API results with WMI."""
@classmethod
@ -575,7 +592,7 @@ class TestProcessWMI(unittest.TestCase):
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestDualProcessImplementation(unittest.TestCase):
class TestDualProcessImplementation(TestCase):
"""
Certain APIs on Windows have 2 internal implementations, one
based on documented Windows APIs, another one based
@ -593,16 +610,6 @@ class TestDualProcessImplementation(unittest.TestCase):
@classmethod
def tearDownClass(cls):
reap_children()
# ---
# same tests as above but mimicks the AccessDenied failure of
# the first (fast) method failing with AD.
def test_name(self):
name = psutil.Process(self.pid).name()
with mock.patch("psutil._psplatform.cext.proc_exe",
side_effect=psutil.AccessDenied(os.getpid())) as fun:
self.assertEqual(psutil.Process(self.pid).name(), name)
assert fun.called
def test_memory_info(self):
mem_1 = psutil.Process(self.pid).memory_info()
@ -618,14 +625,14 @@ class TestDualProcessImplementation(unittest.TestCase):
def test_create_time(self):
ctime = psutil.Process(self.pid).create_time()
with mock.patch("psutil._psplatform.cext.proc_create_time",
with mock.patch("psutil._psplatform.cext.proc_times",
side_effect=OSError(errno.EPERM, "msg")) as fun:
self.assertEqual(psutil.Process(self.pid).create_time(), ctime)
assert fun.called
def test_cpu_times(self):
cpu_times_1 = psutil.Process(self.pid).cpu_times()
with mock.patch("psutil._psplatform.cext.proc_cpu_times",
with mock.patch("psutil._psplatform.cext.proc_times",
side_effect=OSError(errno.EPERM, "msg")) as fun:
cpu_times_2 = psutil.Process(self.pid).cpu_times()
assert fun.called
@ -652,9 +659,23 @@ class TestDualProcessImplementation(unittest.TestCase):
num_handles)
assert fun.called
def test_cmdline(self):
from psutil._pswindows import convert_oserror
for pid in psutil.pids():
try:
a = cext.proc_cmdline(pid, use_peb=True)
b = cext.proc_cmdline(pid, use_peb=False)
except OSError as err:
err = convert_oserror(err)
if not isinstance(err, (psutil.AccessDenied,
psutil.NoSuchProcess)):
raise
else:
self.assertEqual(a, b)
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class RemoteProcessTestCase(unittest.TestCase):
class RemoteProcessTestCase(TestCase):
"""Certain functions require calling ReadProcessMemory.
This trivially works when called on the current process.
Check that this works on other processes, especially when they
@ -738,9 +759,10 @@ class RemoteProcessTestCase(unittest.TestCase):
def test_environ_64(self):
p = psutil.Process(self.proc64.pid)
e = p.environ()
self.assertIn("THINK_OF_A_NUMBER", e)
self.assertEquals(e["THINK_OF_A_NUMBER"], str(os.getpid()))
try:
p.environ()
except psutil.AccessDenied:
pass
# ===================================================================
@ -749,7 +771,7 @@ class RemoteProcessTestCase(unittest.TestCase):
@unittest.skipIf(not WINDOWS, "WINDOWS only")
class TestServices(unittest.TestCase):
class TestServices(TestCase):
def test_win_service_iter(self):
valid_statuses = set([
@ -800,16 +822,22 @@ class TestServices(unittest.TestCase):
self.assertEqual(serv, s)
def test_win_service_get(self):
name = next(psutil.win_service_iter()).name()
ERROR_SERVICE_DOES_NOT_EXIST = \
psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST
ERROR_ACCESS_DENIED = psutil._psplatform.cext.ERROR_ACCESS_DENIED
name = next(psutil.win_service_iter()).name()
with self.assertRaises(psutil.NoSuchProcess) as cm:
psutil.win_service_get(name + '???')
self.assertEqual(cm.exception.name, name + '???')
# test NoSuchProcess
service = psutil.win_service_get(name)
exc = WindowsError(
psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST, "")
if PY3:
args = (0, "msg", 0, ERROR_SERVICE_DOES_NOT_EXIST)
else:
args = (ERROR_SERVICE_DOES_NOT_EXIST, "msg")
exc = WindowsError(*args)
with mock.patch("psutil._psplatform.cext.winservice_query_status",
side_effect=exc):
self.assertRaises(psutil.NoSuchProcess, service.status)
@ -818,8 +846,11 @@ class TestServices(unittest.TestCase):
self.assertRaises(psutil.NoSuchProcess, service.username)
# test AccessDenied
exc = WindowsError(
psutil._psplatform.cext.ERROR_ACCESS_DENIED, "")
if PY3:
args = (0, "msg", 0, ERROR_ACCESS_DENIED)
else:
args = (ERROR_ACCESS_DENIED, "msg")
exc = WindowsError(*args)
with mock.patch("psutil._psplatform.cext.winservice_query_status",
side_effect=exc):
self.assertRaises(psutil.AccessDenied, service.status)
@ -835,4 +866,5 @@ class TestServices(unittest.TestCase):
if __name__ == '__main__':
run_test_module_by_name(__file__)
from psutil.tests.runner import run
run(__file__)

31
third_party/python/psutil/.cirrus.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
freebsd_12_1_py3_task:
freebsd_instance:
image: freebsd-12-1-release-amd64
env:
CIRRUS: 1
install_script:
- pkg install -y python3 gcc py37-pip
script:
- python3 -m pip install --user setuptools
- make clean
- make install
- make test
- make test-memleaks
- PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_access_denied.py
- PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_api_speed.py
freebsd_12_1_py2_task:
freebsd_instance:
image: freebsd-12-1-release-amd64
env:
CIRRUS: 1
install_script:
- pkg install -y python gcc py27-pip
script:
- python2.7 -m pip install --user setuptools ipaddress mock
- make clean
- make install
- make test
- make test-memleaks
- PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_access_denied.py
- PSUTIL_TESTING=1 python3 -Wa scripts/internal/print_api_speed.py

46
third_party/python/psutil/CREDITS поставляемый
Просмотреть файл

@ -57,7 +57,7 @@ N: Arnon Yaari (wiggin15)
W: https://github.com/wiggin15
D: AIX implementation, expert on multiple fronts
I: 517, 607, 610, 1131, 1123, 1130, 1154, 1164, 1174, 1177, 1210, 1214, 1408,
1329, 1276, 1494.
1329, 1276, 1494, 1528.
N: Alex Manuskin
W: https://github.com/amanusk
@ -621,4 +621,46 @@ I: 1491
N: Kamil Rytarowski
W: https://github.com/krytarowski
C: Poland
I: 1526
I: 1526, 1530
N: Athos Ribeiro
W: https://github.com/athos-ribeiro
I: 1585
N: Erwan Le Pape
W: https://github.com/erwan-le-pape
I: 1570
N: Étienne Servais
W: https://github.com/vser1
I: 1607, 1637
N: Bernát Gábor
W: https://github.com/gaborbernat
I: 1565
N: Nathan Houghton
W: https://github.com/n1000
I: 1619
N: Riccardo Schirone
W: https://github.com/ret2libc
C: Milano, Italy
I: 1616
N: Po-Chuan Hsieh
W: https://github.com/sunpoet
C: Taiwan
I: 1646
N: Javad Karabi
W: https://github.com/karabijavad
I: 1648
N: Mike Hommey
W: https://github.com/glandium
I: 1665
N: Anselm Kruis
W: https://github.com/akruis
I: 1695

611
third_party/python/psutil/HISTORY.rst поставляемый
Просмотреть файл

@ -1,5 +1,116 @@
*Bug tracker at https://github.com/giampaolo/psutil/issues*
5.7.0
=====
2020-12-18
**Enhancements**
- 1637_: [SunOS] add partial support for old SunOS 5.10 Update 0 to 3.
- 1648_: [Linux] sensors_temperatures() looks into an additional /sys/device/
directory for additional data. (patch by Javad Karabi)
- 1652_: [Windows] dropped support for Windows XP and Windows Server 2003.
Minimum supported Windows version now is Windows Vista.
- 1671_: [FreeBSD] add CI testing/service for FreeBSD (Cirrus CI).
- 1677_: [Windows] process exe() will succeed for all process PIDs (instead of
raising AccessDenied).
- 1679_: [Windows] net_connections() and Process.connections() are 10% faster.
- 1682_: [PyPy] added CI / test integration for PyPy via Travis.
- 1686_: [Windows] added support for PyPy on Windows.
- 1693_: [Windows] boot_time(), Process.create_time() and users()'s login time
now have 1 micro second precision (before the precision was of 1 second).
**Bug fixes**
- 1538_: [NetBSD] process cwd() may return ENOENT instead of NoSuchProcess.
- 1627_: [Linux] Process.memory_maps() can raise KeyError.
- 1642_: [SunOS] querying basic info for PID 0 results in FileNotFoundError.
- 1646_: [FreeBSD] many Process methods may cause a segfault on FreeBSD 12.0
due to a backward incompatible change in a C type introduced in 12.0.
- 1656_: [Windows] Process.memory_full_info() raises AccessDenied even for the
current user and os.getpid().
- 1660_: [Windows] Process.open_files() complete rewrite + check of errors.
- 1662_: [Windows] process exe() may raise WinError 0.
- 1665_: [Linux] disk_io_counters() does not take into account extra fields
added to recent kernels. (patch by Mike Hommey)
- 1672_: use the right C type when dealing with PIDs (int or long). Thus far
(long) was almost always assumed, which is wrong on most platforms.
- 1673_: [OpenBSD] Process connections(), num_fds() and threads() returned
improper exception if process is gone.
- 1674_: [SunOS] disk_partitions() may raise OSError.
- 1684_: [Linux] disk_io_counters() may raise ValueError on systems not
having /proc/diskstats.
- 1695_: [Linux] could not compile on kernels <= 2.6.13 due to
PSUTIL_HAVE_IOPRIO not being defined. (patch by Anselm Kruis)
5.6.7
=====
2019-11-26
**Bug fixes**
- 1630_: [Windows] can't compile source distribution due to C syntax error.
5.6.6
=====
2019-11-25
**Bug fixes**
- 1179_: [Linux] Process cmdline() now takes into account misbehaving processes
renaming the command line and using inappropriate chars to separate args.
- 1616_: use of Py_DECREF instead of Py_CLEAR will result in double free and
segfault
(`CVE-2019-18874 <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-18874>`__).
(patch by Riccardo Schirone)
- 1619_: [OpenBSD] compilation fails due to C syntax error. (patch by Nathan
Houghton)
5.6.5
=====
2019-11-06
**Bug fixes**
- 1615_: remove pyproject.toml as it was causing installation issues.
5.6.4
=====
2019-11-04
**Enhancements**
- 1527_: [Linux] added Process.cpu_times().iowait counter, which is the time
spent waiting for blocking I/O to complete.
- 1565_: add PEP 517/8 build backend and requirements specification for better
pip integration. (patch by Bernát Gábor)
**Bug fixes**
- 875_: [Windows] Process' cmdline(), environ() or cwd() may occasionally fail
with ERROR_PARTIAL_COPY which now gets translated to AccessDenied.
- 1126_: [Linux] cpu_affinity() segfaults on CentOS 5 / manylinux.
cpu_affinity() support for CentOS 5 was removed.
- 1528_: [AIX] compilation error on AIX 7.2 due to 32 vs 64 bit differences.
(patch by Arnon Yaari)
- 1535_: 'type' and 'family' fields returned by net_connections() are not
always turned into enums.
- 1536_: [NetBSD] process cmdline() erroneously raise ZombieProcess error if
cmdline has non encodable chars.
- 1546_: usage percent may be rounded to 0 on Python 2.
- 1552_: [Windows] getloadavg() math for calculating 5 and 15 mins values is
incorrect.
- 1568_: [Linux] use CC compiler env var if defined.
- 1570_: [Windows] `NtWow64*` syscalls fail to raise the proper error code
- 1585_: [OSX] calling close() (in C) on possible negative integers. (patch
by Athos Ribeiro)
- 1606_: [SunOS] compilation fails on SunOS 5.10. (patch by vser1)
5.6.3
=====
@ -3528,3 +3639,503 @@ DeprecationWarning.
.. _1498: https://github.com/giampaolo/psutil/issues/1498
.. _1499: https://github.com/giampaolo/psutil/issues/1499
.. _1500: https://github.com/giampaolo/psutil/issues/1500
.. _1501: https://github.com/giampaolo/psutil/issues/1501
.. _1502: https://github.com/giampaolo/psutil/issues/1502
.. _1503: https://github.com/giampaolo/psutil/issues/1503
.. _1504: https://github.com/giampaolo/psutil/issues/1504
.. _1505: https://github.com/giampaolo/psutil/issues/1505
.. _1506: https://github.com/giampaolo/psutil/issues/1506
.. _1507: https://github.com/giampaolo/psutil/issues/1507
.. _1508: https://github.com/giampaolo/psutil/issues/1508
.. _1509: https://github.com/giampaolo/psutil/issues/1509
.. _1510: https://github.com/giampaolo/psutil/issues/1510
.. _1511: https://github.com/giampaolo/psutil/issues/1511
.. _1512: https://github.com/giampaolo/psutil/issues/1512
.. _1513: https://github.com/giampaolo/psutil/issues/1513
.. _1514: https://github.com/giampaolo/psutil/issues/1514
.. _1515: https://github.com/giampaolo/psutil/issues/1515
.. _1516: https://github.com/giampaolo/psutil/issues/1516
.. _1517: https://github.com/giampaolo/psutil/issues/1517
.. _1518: https://github.com/giampaolo/psutil/issues/1518
.. _1519: https://github.com/giampaolo/psutil/issues/1519
.. _1520: https://github.com/giampaolo/psutil/issues/1520
.. _1521: https://github.com/giampaolo/psutil/issues/1521
.. _1522: https://github.com/giampaolo/psutil/issues/1522
.. _1523: https://github.com/giampaolo/psutil/issues/1523
.. _1524: https://github.com/giampaolo/psutil/issues/1524
.. _1525: https://github.com/giampaolo/psutil/issues/1525
.. _1526: https://github.com/giampaolo/psutil/issues/1526
.. _1527: https://github.com/giampaolo/psutil/issues/1527
.. _1528: https://github.com/giampaolo/psutil/issues/1528
.. _1529: https://github.com/giampaolo/psutil/issues/1529
.. _1530: https://github.com/giampaolo/psutil/issues/1530
.. _1531: https://github.com/giampaolo/psutil/issues/1531
.. _1532: https://github.com/giampaolo/psutil/issues/1532
.. _1533: https://github.com/giampaolo/psutil/issues/1533
.. _1534: https://github.com/giampaolo/psutil/issues/1534
.. _1535: https://github.com/giampaolo/psutil/issues/1535
.. _1536: https://github.com/giampaolo/psutil/issues/1536
.. _1537: https://github.com/giampaolo/psutil/issues/1537
.. _1538: https://github.com/giampaolo/psutil/issues/1538
.. _1539: https://github.com/giampaolo/psutil/issues/1539
.. _1540: https://github.com/giampaolo/psutil/issues/1540
.. _1541: https://github.com/giampaolo/psutil/issues/1541
.. _1542: https://github.com/giampaolo/psutil/issues/1542
.. _1543: https://github.com/giampaolo/psutil/issues/1543
.. _1544: https://github.com/giampaolo/psutil/issues/1544
.. _1545: https://github.com/giampaolo/psutil/issues/1545
.. _1546: https://github.com/giampaolo/psutil/issues/1546
.. _1547: https://github.com/giampaolo/psutil/issues/1547
.. _1548: https://github.com/giampaolo/psutil/issues/1548
.. _1549: https://github.com/giampaolo/psutil/issues/1549
.. _1550: https://github.com/giampaolo/psutil/issues/1550
.. _1551: https://github.com/giampaolo/psutil/issues/1551
.. _1552: https://github.com/giampaolo/psutil/issues/1552
.. _1553: https://github.com/giampaolo/psutil/issues/1553
.. _1554: https://github.com/giampaolo/psutil/issues/1554
.. _1555: https://github.com/giampaolo/psutil/issues/1555
.. _1556: https://github.com/giampaolo/psutil/issues/1556
.. _1557: https://github.com/giampaolo/psutil/issues/1557
.. _1558: https://github.com/giampaolo/psutil/issues/1558
.. _1559: https://github.com/giampaolo/psutil/issues/1559
.. _1560: https://github.com/giampaolo/psutil/issues/1560
.. _1561: https://github.com/giampaolo/psutil/issues/1561
.. _1562: https://github.com/giampaolo/psutil/issues/1562
.. _1563: https://github.com/giampaolo/psutil/issues/1563
.. _1564: https://github.com/giampaolo/psutil/issues/1564
.. _1565: https://github.com/giampaolo/psutil/issues/1565
.. _1566: https://github.com/giampaolo/psutil/issues/1566
.. _1567: https://github.com/giampaolo/psutil/issues/1567
.. _1568: https://github.com/giampaolo/psutil/issues/1568
.. _1569: https://github.com/giampaolo/psutil/issues/1569
.. _1570: https://github.com/giampaolo/psutil/issues/1570
.. _1571: https://github.com/giampaolo/psutil/issues/1571
.. _1572: https://github.com/giampaolo/psutil/issues/1572
.. _1573: https://github.com/giampaolo/psutil/issues/1573
.. _1574: https://github.com/giampaolo/psutil/issues/1574
.. _1575: https://github.com/giampaolo/psutil/issues/1575
.. _1576: https://github.com/giampaolo/psutil/issues/1576
.. _1577: https://github.com/giampaolo/psutil/issues/1577
.. _1578: https://github.com/giampaolo/psutil/issues/1578
.. _1579: https://github.com/giampaolo/psutil/issues/1579
.. _1580: https://github.com/giampaolo/psutil/issues/1580
.. _1581: https://github.com/giampaolo/psutil/issues/1581
.. _1582: https://github.com/giampaolo/psutil/issues/1582
.. _1583: https://github.com/giampaolo/psutil/issues/1583
.. _1584: https://github.com/giampaolo/psutil/issues/1584
.. _1585: https://github.com/giampaolo/psutil/issues/1585
.. _1586: https://github.com/giampaolo/psutil/issues/1586
.. _1587: https://github.com/giampaolo/psutil/issues/1587
.. _1588: https://github.com/giampaolo/psutil/issues/1588
.. _1589: https://github.com/giampaolo/psutil/issues/1589
.. _1590: https://github.com/giampaolo/psutil/issues/1590
.. _1591: https://github.com/giampaolo/psutil/issues/1591
.. _1592: https://github.com/giampaolo/psutil/issues/1592
.. _1593: https://github.com/giampaolo/psutil/issues/1593
.. _1594: https://github.com/giampaolo/psutil/issues/1594
.. _1595: https://github.com/giampaolo/psutil/issues/1595
.. _1596: https://github.com/giampaolo/psutil/issues/1596
.. _1597: https://github.com/giampaolo/psutil/issues/1597
.. _1598: https://github.com/giampaolo/psutil/issues/1598
.. _1599: https://github.com/giampaolo/psutil/issues/1599
.. _1600: https://github.com/giampaolo/psutil/issues/1600
.. _1601: https://github.com/giampaolo/psutil/issues/1601
.. _1602: https://github.com/giampaolo/psutil/issues/1602
.. _1603: https://github.com/giampaolo/psutil/issues/1603
.. _1604: https://github.com/giampaolo/psutil/issues/1604
.. _1605: https://github.com/giampaolo/psutil/issues/1605
.. _1606: https://github.com/giampaolo/psutil/issues/1606
.. _1607: https://github.com/giampaolo/psutil/issues/1607
.. _1608: https://github.com/giampaolo/psutil/issues/1608
.. _1609: https://github.com/giampaolo/psutil/issues/1609
.. _1610: https://github.com/giampaolo/psutil/issues/1610
.. _1611: https://github.com/giampaolo/psutil/issues/1611
.. _1612: https://github.com/giampaolo/psutil/issues/1612
.. _1613: https://github.com/giampaolo/psutil/issues/1613
.. _1614: https://github.com/giampaolo/psutil/issues/1614
.. _1615: https://github.com/giampaolo/psutil/issues/1615
.. _1616: https://github.com/giampaolo/psutil/issues/1616
.. _1617: https://github.com/giampaolo/psutil/issues/1617
.. _1618: https://github.com/giampaolo/psutil/issues/1618
.. _1619: https://github.com/giampaolo/psutil/issues/1619
.. _1620: https://github.com/giampaolo/psutil/issues/1620
.. _1621: https://github.com/giampaolo/psutil/issues/1621
.. _1622: https://github.com/giampaolo/psutil/issues/1622
.. _1623: https://github.com/giampaolo/psutil/issues/1623
.. _1624: https://github.com/giampaolo/psutil/issues/1624
.. _1625: https://github.com/giampaolo/psutil/issues/1625
.. _1626: https://github.com/giampaolo/psutil/issues/1626
.. _1627: https://github.com/giampaolo/psutil/issues/1627
.. _1628: https://github.com/giampaolo/psutil/issues/1628
.. _1629: https://github.com/giampaolo/psutil/issues/1629
.. _1630: https://github.com/giampaolo/psutil/issues/1630
.. _1631: https://github.com/giampaolo/psutil/issues/1631
.. _1632: https://github.com/giampaolo/psutil/issues/1632
.. _1633: https://github.com/giampaolo/psutil/issues/1633
.. _1634: https://github.com/giampaolo/psutil/issues/1634
.. _1635: https://github.com/giampaolo/psutil/issues/1635
.. _1636: https://github.com/giampaolo/psutil/issues/1636
.. _1637: https://github.com/giampaolo/psutil/issues/1637
.. _1638: https://github.com/giampaolo/psutil/issues/1638
.. _1639: https://github.com/giampaolo/psutil/issues/1639
.. _1640: https://github.com/giampaolo/psutil/issues/1640
.. _1641: https://github.com/giampaolo/psutil/issues/1641
.. _1642: https://github.com/giampaolo/psutil/issues/1642
.. _1643: https://github.com/giampaolo/psutil/issues/1643
.. _1644: https://github.com/giampaolo/psutil/issues/1644
.. _1645: https://github.com/giampaolo/psutil/issues/1645
.. _1646: https://github.com/giampaolo/psutil/issues/1646
.. _1647: https://github.com/giampaolo/psutil/issues/1647
.. _1648: https://github.com/giampaolo/psutil/issues/1648
.. _1649: https://github.com/giampaolo/psutil/issues/1649
.. _1650: https://github.com/giampaolo/psutil/issues/1650
.. _1651: https://github.com/giampaolo/psutil/issues/1651
.. _1652: https://github.com/giampaolo/psutil/issues/1652
.. _1653: https://github.com/giampaolo/psutil/issues/1653
.. _1654: https://github.com/giampaolo/psutil/issues/1654
.. _1655: https://github.com/giampaolo/psutil/issues/1655
.. _1656: https://github.com/giampaolo/psutil/issues/1656
.. _1657: https://github.com/giampaolo/psutil/issues/1657
.. _1658: https://github.com/giampaolo/psutil/issues/1658
.. _1659: https://github.com/giampaolo/psutil/issues/1659
.. _1660: https://github.com/giampaolo/psutil/issues/1660
.. _1661: https://github.com/giampaolo/psutil/issues/1661
.. _1662: https://github.com/giampaolo/psutil/issues/1662
.. _1663: https://github.com/giampaolo/psutil/issues/1663
.. _1664: https://github.com/giampaolo/psutil/issues/1664
.. _1665: https://github.com/giampaolo/psutil/issues/1665
.. _1666: https://github.com/giampaolo/psutil/issues/1666
.. _1667: https://github.com/giampaolo/psutil/issues/1667
.. _1668: https://github.com/giampaolo/psutil/issues/1668
.. _1669: https://github.com/giampaolo/psutil/issues/1669
.. _1670: https://github.com/giampaolo/psutil/issues/1670
.. _1671: https://github.com/giampaolo/psutil/issues/1671
.. _1672: https://github.com/giampaolo/psutil/issues/1672
.. _1673: https://github.com/giampaolo/psutil/issues/1673
.. _1674: https://github.com/giampaolo/psutil/issues/1674
.. _1675: https://github.com/giampaolo/psutil/issues/1675
.. _1676: https://github.com/giampaolo/psutil/issues/1676
.. _1677: https://github.com/giampaolo/psutil/issues/1677
.. _1678: https://github.com/giampaolo/psutil/issues/1678
.. _1679: https://github.com/giampaolo/psutil/issues/1679
.. _1680: https://github.com/giampaolo/psutil/issues/1680
.. _1681: https://github.com/giampaolo/psutil/issues/1681
.. _1682: https://github.com/giampaolo/psutil/issues/1682
.. _1683: https://github.com/giampaolo/psutil/issues/1683
.. _1684: https://github.com/giampaolo/psutil/issues/1684
.. _1685: https://github.com/giampaolo/psutil/issues/1685
.. _1686: https://github.com/giampaolo/psutil/issues/1686
.. _1687: https://github.com/giampaolo/psutil/issues/1687
.. _1688: https://github.com/giampaolo/psutil/issues/1688
.. _1689: https://github.com/giampaolo/psutil/issues/1689
.. _1690: https://github.com/giampaolo/psutil/issues/1690
.. _1691: https://github.com/giampaolo/psutil/issues/1691
.. _1692: https://github.com/giampaolo/psutil/issues/1692
.. _1693: https://github.com/giampaolo/psutil/issues/1693
.. _1694: https://github.com/giampaolo/psutil/issues/1694
.. _1695: https://github.com/giampaolo/psutil/issues/1695
.. _1696: https://github.com/giampaolo/psutil/issues/1696
.. _1697: https://github.com/giampaolo/psutil/issues/1697
.. _1698: https://github.com/giampaolo/psutil/issues/1698
.. _1699: https://github.com/giampaolo/psutil/issues/1699
.. _1700: https://github.com/giampaolo/psutil/issues/1700
.. _1701: https://github.com/giampaolo/psutil/issues/1701
.. _1702: https://github.com/giampaolo/psutil/issues/1702
.. _1703: https://github.com/giampaolo/psutil/issues/1703
.. _1704: https://github.com/giampaolo/psutil/issues/1704
.. _1705: https://github.com/giampaolo/psutil/issues/1705
.. _1706: https://github.com/giampaolo/psutil/issues/1706
.. _1707: https://github.com/giampaolo/psutil/issues/1707
.. _1708: https://github.com/giampaolo/psutil/issues/1708
.. _1709: https://github.com/giampaolo/psutil/issues/1709
.. _1710: https://github.com/giampaolo/psutil/issues/1710
.. _1711: https://github.com/giampaolo/psutil/issues/1711
.. _1712: https://github.com/giampaolo/psutil/issues/1712
.. _1713: https://github.com/giampaolo/psutil/issues/1713
.. _1714: https://github.com/giampaolo/psutil/issues/1714
.. _1715: https://github.com/giampaolo/psutil/issues/1715
.. _1716: https://github.com/giampaolo/psutil/issues/1716
.. _1717: https://github.com/giampaolo/psutil/issues/1717
.. _1718: https://github.com/giampaolo/psutil/issues/1718
.. _1719: https://github.com/giampaolo/psutil/issues/1719
.. _1720: https://github.com/giampaolo/psutil/issues/1720
.. _1721: https://github.com/giampaolo/psutil/issues/1721
.. _1722: https://github.com/giampaolo/psutil/issues/1722
.. _1723: https://github.com/giampaolo/psutil/issues/1723
.. _1724: https://github.com/giampaolo/psutil/issues/1724
.. _1725: https://github.com/giampaolo/psutil/issues/1725
.. _1726: https://github.com/giampaolo/psutil/issues/1726
.. _1727: https://github.com/giampaolo/psutil/issues/1727
.. _1728: https://github.com/giampaolo/psutil/issues/1728
.. _1729: https://github.com/giampaolo/psutil/issues/1729
.. _1730: https://github.com/giampaolo/psutil/issues/1730
.. _1731: https://github.com/giampaolo/psutil/issues/1731
.. _1732: https://github.com/giampaolo/psutil/issues/1732
.. _1733: https://github.com/giampaolo/psutil/issues/1733
.. _1734: https://github.com/giampaolo/psutil/issues/1734
.. _1735: https://github.com/giampaolo/psutil/issues/1735
.. _1736: https://github.com/giampaolo/psutil/issues/1736
.. _1737: https://github.com/giampaolo/psutil/issues/1737
.. _1738: https://github.com/giampaolo/psutil/issues/1738
.. _1739: https://github.com/giampaolo/psutil/issues/1739
.. _1740: https://github.com/giampaolo/psutil/issues/1740
.. _1741: https://github.com/giampaolo/psutil/issues/1741
.. _1742: https://github.com/giampaolo/psutil/issues/1742
.. _1743: https://github.com/giampaolo/psutil/issues/1743
.. _1744: https://github.com/giampaolo/psutil/issues/1744
.. _1745: https://github.com/giampaolo/psutil/issues/1745
.. _1746: https://github.com/giampaolo/psutil/issues/1746
.. _1747: https://github.com/giampaolo/psutil/issues/1747
.. _1748: https://github.com/giampaolo/psutil/issues/1748
.. _1749: https://github.com/giampaolo/psutil/issues/1749
.. _1750: https://github.com/giampaolo/psutil/issues/1750
.. _1751: https://github.com/giampaolo/psutil/issues/1751
.. _1752: https://github.com/giampaolo/psutil/issues/1752
.. _1753: https://github.com/giampaolo/psutil/issues/1753
.. _1754: https://github.com/giampaolo/psutil/issues/1754
.. _1755: https://github.com/giampaolo/psutil/issues/1755
.. _1756: https://github.com/giampaolo/psutil/issues/1756
.. _1757: https://github.com/giampaolo/psutil/issues/1757
.. _1758: https://github.com/giampaolo/psutil/issues/1758
.. _1759: https://github.com/giampaolo/psutil/issues/1759
.. _1760: https://github.com/giampaolo/psutil/issues/1760
.. _1761: https://github.com/giampaolo/psutil/issues/1761
.. _1762: https://github.com/giampaolo/psutil/issues/1762
.. _1763: https://github.com/giampaolo/psutil/issues/1763
.. _1764: https://github.com/giampaolo/psutil/issues/1764
.. _1765: https://github.com/giampaolo/psutil/issues/1765
.. _1766: https://github.com/giampaolo/psutil/issues/1766
.. _1767: https://github.com/giampaolo/psutil/issues/1767
.. _1768: https://github.com/giampaolo/psutil/issues/1768
.. _1769: https://github.com/giampaolo/psutil/issues/1769
.. _1770: https://github.com/giampaolo/psutil/issues/1770
.. _1771: https://github.com/giampaolo/psutil/issues/1771
.. _1772: https://github.com/giampaolo/psutil/issues/1772
.. _1773: https://github.com/giampaolo/psutil/issues/1773
.. _1774: https://github.com/giampaolo/psutil/issues/1774
.. _1775: https://github.com/giampaolo/psutil/issues/1775
.. _1776: https://github.com/giampaolo/psutil/issues/1776
.. _1777: https://github.com/giampaolo/psutil/issues/1777
.. _1778: https://github.com/giampaolo/psutil/issues/1778
.. _1779: https://github.com/giampaolo/psutil/issues/1779
.. _1780: https://github.com/giampaolo/psutil/issues/1780
.. _1781: https://github.com/giampaolo/psutil/issues/1781
.. _1782: https://github.com/giampaolo/psutil/issues/1782
.. _1783: https://github.com/giampaolo/psutil/issues/1783
.. _1784: https://github.com/giampaolo/psutil/issues/1784
.. _1785: https://github.com/giampaolo/psutil/issues/1785
.. _1786: https://github.com/giampaolo/psutil/issues/1786
.. _1787: https://github.com/giampaolo/psutil/issues/1787
.. _1788: https://github.com/giampaolo/psutil/issues/1788
.. _1789: https://github.com/giampaolo/psutil/issues/1789
.. _1790: https://github.com/giampaolo/psutil/issues/1790
.. _1791: https://github.com/giampaolo/psutil/issues/1791
.. _1792: https://github.com/giampaolo/psutil/issues/1792
.. _1793: https://github.com/giampaolo/psutil/issues/1793
.. _1794: https://github.com/giampaolo/psutil/issues/1794
.. _1795: https://github.com/giampaolo/psutil/issues/1795
.. _1796: https://github.com/giampaolo/psutil/issues/1796
.. _1797: https://github.com/giampaolo/psutil/issues/1797
.. _1798: https://github.com/giampaolo/psutil/issues/1798
.. _1799: https://github.com/giampaolo/psutil/issues/1799
.. _1800: https://github.com/giampaolo/psutil/issues/1800
.. _1801: https://github.com/giampaolo/psutil/issues/1801
.. _1802: https://github.com/giampaolo/psutil/issues/1802
.. _1803: https://github.com/giampaolo/psutil/issues/1803
.. _1804: https://github.com/giampaolo/psutil/issues/1804
.. _1805: https://github.com/giampaolo/psutil/issues/1805
.. _1806: https://github.com/giampaolo/psutil/issues/1806
.. _1807: https://github.com/giampaolo/psutil/issues/1807
.. _1808: https://github.com/giampaolo/psutil/issues/1808
.. _1809: https://github.com/giampaolo/psutil/issues/1809
.. _1810: https://github.com/giampaolo/psutil/issues/1810
.. _1811: https://github.com/giampaolo/psutil/issues/1811
.. _1812: https://github.com/giampaolo/psutil/issues/1812
.. _1813: https://github.com/giampaolo/psutil/issues/1813
.. _1814: https://github.com/giampaolo/psutil/issues/1814
.. _1815: https://github.com/giampaolo/psutil/issues/1815
.. _1816: https://github.com/giampaolo/psutil/issues/1816
.. _1817: https://github.com/giampaolo/psutil/issues/1817
.. _1818: https://github.com/giampaolo/psutil/issues/1818
.. _1819: https://github.com/giampaolo/psutil/issues/1819
.. _1820: https://github.com/giampaolo/psutil/issues/1820
.. _1821: https://github.com/giampaolo/psutil/issues/1821
.. _1822: https://github.com/giampaolo/psutil/issues/1822
.. _1823: https://github.com/giampaolo/psutil/issues/1823
.. _1824: https://github.com/giampaolo/psutil/issues/1824
.. _1825: https://github.com/giampaolo/psutil/issues/1825
.. _1826: https://github.com/giampaolo/psutil/issues/1826
.. _1827: https://github.com/giampaolo/psutil/issues/1827
.. _1828: https://github.com/giampaolo/psutil/issues/1828
.. _1829: https://github.com/giampaolo/psutil/issues/1829
.. _1830: https://github.com/giampaolo/psutil/issues/1830
.. _1831: https://github.com/giampaolo/psutil/issues/1831
.. _1832: https://github.com/giampaolo/psutil/issues/1832
.. _1833: https://github.com/giampaolo/psutil/issues/1833
.. _1834: https://github.com/giampaolo/psutil/issues/1834
.. _1835: https://github.com/giampaolo/psutil/issues/1835
.. _1836: https://github.com/giampaolo/psutil/issues/1836
.. _1837: https://github.com/giampaolo/psutil/issues/1837
.. _1838: https://github.com/giampaolo/psutil/issues/1838
.. _1839: https://github.com/giampaolo/psutil/issues/1839
.. _1840: https://github.com/giampaolo/psutil/issues/1840
.. _1841: https://github.com/giampaolo/psutil/issues/1841
.. _1842: https://github.com/giampaolo/psutil/issues/1842
.. _1843: https://github.com/giampaolo/psutil/issues/1843
.. _1844: https://github.com/giampaolo/psutil/issues/1844
.. _1845: https://github.com/giampaolo/psutil/issues/1845
.. _1846: https://github.com/giampaolo/psutil/issues/1846
.. _1847: https://github.com/giampaolo/psutil/issues/1847
.. _1848: https://github.com/giampaolo/psutil/issues/1848
.. _1849: https://github.com/giampaolo/psutil/issues/1849
.. _1850: https://github.com/giampaolo/psutil/issues/1850
.. _1851: https://github.com/giampaolo/psutil/issues/1851
.. _1852: https://github.com/giampaolo/psutil/issues/1852
.. _1853: https://github.com/giampaolo/psutil/issues/1853
.. _1854: https://github.com/giampaolo/psutil/issues/1854
.. _1855: https://github.com/giampaolo/psutil/issues/1855
.. _1856: https://github.com/giampaolo/psutil/issues/1856
.. _1857: https://github.com/giampaolo/psutil/issues/1857
.. _1858: https://github.com/giampaolo/psutil/issues/1858
.. _1859: https://github.com/giampaolo/psutil/issues/1859
.. _1860: https://github.com/giampaolo/psutil/issues/1860
.. _1861: https://github.com/giampaolo/psutil/issues/1861
.. _1862: https://github.com/giampaolo/psutil/issues/1862
.. _1863: https://github.com/giampaolo/psutil/issues/1863
.. _1864: https://github.com/giampaolo/psutil/issues/1864
.. _1865: https://github.com/giampaolo/psutil/issues/1865
.. _1866: https://github.com/giampaolo/psutil/issues/1866
.. _1867: https://github.com/giampaolo/psutil/issues/1867
.. _1868: https://github.com/giampaolo/psutil/issues/1868
.. _1869: https://github.com/giampaolo/psutil/issues/1869
.. _1870: https://github.com/giampaolo/psutil/issues/1870
.. _1871: https://github.com/giampaolo/psutil/issues/1871
.. _1872: https://github.com/giampaolo/psutil/issues/1872
.. _1873: https://github.com/giampaolo/psutil/issues/1873
.. _1874: https://github.com/giampaolo/psutil/issues/1874
.. _1875: https://github.com/giampaolo/psutil/issues/1875
.. _1876: https://github.com/giampaolo/psutil/issues/1876
.. _1877: https://github.com/giampaolo/psutil/issues/1877
.. _1878: https://github.com/giampaolo/psutil/issues/1878
.. _1879: https://github.com/giampaolo/psutil/issues/1879
.. _1880: https://github.com/giampaolo/psutil/issues/1880
.. _1881: https://github.com/giampaolo/psutil/issues/1881
.. _1882: https://github.com/giampaolo/psutil/issues/1882
.. _1883: https://github.com/giampaolo/psutil/issues/1883
.. _1884: https://github.com/giampaolo/psutil/issues/1884
.. _1885: https://github.com/giampaolo/psutil/issues/1885
.. _1886: https://github.com/giampaolo/psutil/issues/1886
.. _1887: https://github.com/giampaolo/psutil/issues/1887
.. _1888: https://github.com/giampaolo/psutil/issues/1888
.. _1889: https://github.com/giampaolo/psutil/issues/1889
.. _1890: https://github.com/giampaolo/psutil/issues/1890
.. _1891: https://github.com/giampaolo/psutil/issues/1891
.. _1892: https://github.com/giampaolo/psutil/issues/1892
.. _1893: https://github.com/giampaolo/psutil/issues/1893
.. _1894: https://github.com/giampaolo/psutil/issues/1894
.. _1895: https://github.com/giampaolo/psutil/issues/1895
.. _1896: https://github.com/giampaolo/psutil/issues/1896
.. _1897: https://github.com/giampaolo/psutil/issues/1897
.. _1898: https://github.com/giampaolo/psutil/issues/1898
.. _1899: https://github.com/giampaolo/psutil/issues/1899
.. _1900: https://github.com/giampaolo/psutil/issues/1900
.. _1901: https://github.com/giampaolo/psutil/issues/1901
.. _1902: https://github.com/giampaolo/psutil/issues/1902
.. _1903: https://github.com/giampaolo/psutil/issues/1903
.. _1904: https://github.com/giampaolo/psutil/issues/1904
.. _1905: https://github.com/giampaolo/psutil/issues/1905
.. _1906: https://github.com/giampaolo/psutil/issues/1906
.. _1907: https://github.com/giampaolo/psutil/issues/1907
.. _1908: https://github.com/giampaolo/psutil/issues/1908
.. _1909: https://github.com/giampaolo/psutil/issues/1909
.. _1910: https://github.com/giampaolo/psutil/issues/1910
.. _1911: https://github.com/giampaolo/psutil/issues/1911
.. _1912: https://github.com/giampaolo/psutil/issues/1912
.. _1913: https://github.com/giampaolo/psutil/issues/1913
.. _1914: https://github.com/giampaolo/psutil/issues/1914
.. _1915: https://github.com/giampaolo/psutil/issues/1915
.. _1916: https://github.com/giampaolo/psutil/issues/1916
.. _1917: https://github.com/giampaolo/psutil/issues/1917
.. _1918: https://github.com/giampaolo/psutil/issues/1918
.. _1919: https://github.com/giampaolo/psutil/issues/1919
.. _1920: https://github.com/giampaolo/psutil/issues/1920
.. _1921: https://github.com/giampaolo/psutil/issues/1921
.. _1922: https://github.com/giampaolo/psutil/issues/1922
.. _1923: https://github.com/giampaolo/psutil/issues/1923
.. _1924: https://github.com/giampaolo/psutil/issues/1924
.. _1925: https://github.com/giampaolo/psutil/issues/1925
.. _1926: https://github.com/giampaolo/psutil/issues/1926
.. _1927: https://github.com/giampaolo/psutil/issues/1927
.. _1928: https://github.com/giampaolo/psutil/issues/1928
.. _1929: https://github.com/giampaolo/psutil/issues/1929
.. _1930: https://github.com/giampaolo/psutil/issues/1930
.. _1931: https://github.com/giampaolo/psutil/issues/1931
.. _1932: https://github.com/giampaolo/psutil/issues/1932
.. _1933: https://github.com/giampaolo/psutil/issues/1933
.. _1934: https://github.com/giampaolo/psutil/issues/1934
.. _1935: https://github.com/giampaolo/psutil/issues/1935
.. _1936: https://github.com/giampaolo/psutil/issues/1936
.. _1937: https://github.com/giampaolo/psutil/issues/1937
.. _1938: https://github.com/giampaolo/psutil/issues/1938
.. _1939: https://github.com/giampaolo/psutil/issues/1939
.. _1940: https://github.com/giampaolo/psutil/issues/1940
.. _1941: https://github.com/giampaolo/psutil/issues/1941
.. _1942: https://github.com/giampaolo/psutil/issues/1942
.. _1943: https://github.com/giampaolo/psutil/issues/1943
.. _1944: https://github.com/giampaolo/psutil/issues/1944
.. _1945: https://github.com/giampaolo/psutil/issues/1945
.. _1946: https://github.com/giampaolo/psutil/issues/1946
.. _1947: https://github.com/giampaolo/psutil/issues/1947
.. _1948: https://github.com/giampaolo/psutil/issues/1948
.. _1949: https://github.com/giampaolo/psutil/issues/1949
.. _1950: https://github.com/giampaolo/psutil/issues/1950
.. _1951: https://github.com/giampaolo/psutil/issues/1951
.. _1952: https://github.com/giampaolo/psutil/issues/1952
.. _1953: https://github.com/giampaolo/psutil/issues/1953
.. _1954: https://github.com/giampaolo/psutil/issues/1954
.. _1955: https://github.com/giampaolo/psutil/issues/1955
.. _1956: https://github.com/giampaolo/psutil/issues/1956
.. _1957: https://github.com/giampaolo/psutil/issues/1957
.. _1958: https://github.com/giampaolo/psutil/issues/1958
.. _1959: https://github.com/giampaolo/psutil/issues/1959
.. _1960: https://github.com/giampaolo/psutil/issues/1960
.. _1961: https://github.com/giampaolo/psutil/issues/1961
.. _1962: https://github.com/giampaolo/psutil/issues/1962
.. _1963: https://github.com/giampaolo/psutil/issues/1963
.. _1964: https://github.com/giampaolo/psutil/issues/1964
.. _1965: https://github.com/giampaolo/psutil/issues/1965
.. _1966: https://github.com/giampaolo/psutil/issues/1966
.. _1967: https://github.com/giampaolo/psutil/issues/1967
.. _1968: https://github.com/giampaolo/psutil/issues/1968
.. _1969: https://github.com/giampaolo/psutil/issues/1969
.. _1970: https://github.com/giampaolo/psutil/issues/1970
.. _1971: https://github.com/giampaolo/psutil/issues/1971
.. _1972: https://github.com/giampaolo/psutil/issues/1972
.. _1973: https://github.com/giampaolo/psutil/issues/1973
.. _1974: https://github.com/giampaolo/psutil/issues/1974
.. _1975: https://github.com/giampaolo/psutil/issues/1975
.. _1976: https://github.com/giampaolo/psutil/issues/1976
.. _1977: https://github.com/giampaolo/psutil/issues/1977
.. _1978: https://github.com/giampaolo/psutil/issues/1978
.. _1979: https://github.com/giampaolo/psutil/issues/1979
.. _1980: https://github.com/giampaolo/psutil/issues/1980
.. _1981: https://github.com/giampaolo/psutil/issues/1981
.. _1982: https://github.com/giampaolo/psutil/issues/1982
.. _1983: https://github.com/giampaolo/psutil/issues/1983
.. _1984: https://github.com/giampaolo/psutil/issues/1984
.. _1985: https://github.com/giampaolo/psutil/issues/1985
.. _1986: https://github.com/giampaolo/psutil/issues/1986
.. _1987: https://github.com/giampaolo/psutil/issues/1987
.. _1988: https://github.com/giampaolo/psutil/issues/1988
.. _1989: https://github.com/giampaolo/psutil/issues/1989
.. _1990: https://github.com/giampaolo/psutil/issues/1990
.. _1991: https://github.com/giampaolo/psutil/issues/1991
.. _1992: https://github.com/giampaolo/psutil/issues/1992
.. _1993: https://github.com/giampaolo/psutil/issues/1993
.. _1994: https://github.com/giampaolo/psutil/issues/1994
.. _1995: https://github.com/giampaolo/psutil/issues/1995
.. _1996: https://github.com/giampaolo/psutil/issues/1996
.. _1997: https://github.com/giampaolo/psutil/issues/1997
.. _1998: https://github.com/giampaolo/psutil/issues/1998
.. _1999: https://github.com/giampaolo/psutil/issues/1999
.. _2000: https://github.com/giampaolo/psutil/issues/2000

2
third_party/python/psutil/INSTALL.rst поставляемый
Просмотреть файл

@ -93,7 +93,7 @@ OpenBSD
::
export PKG_PATH=http://ftp.eu.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/
pkg_add -v python3 gcc
pkg_add -v python gcc
python3 -m pip install psutil
NetBSD

20
third_party/python/psutil/MANIFEST.in поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
include .cirrus.yml
include .coveragerc
include .gitignore
include CREDITS
@ -64,19 +65,25 @@ include psutil/arch/solaris/environ.c
include psutil/arch/solaris/environ.h
include psutil/arch/solaris/v10/ifaddrs.c
include psutil/arch/solaris/v10/ifaddrs.h
include psutil/arch/windows/global.c
include psutil/arch/windows/global.h
include psutil/arch/windows/inet_ntop.c
include psutil/arch/windows/inet_ntop.h
include psutil/arch/windows/cpu.c
include psutil/arch/windows/cpu.h
include psutil/arch/windows/disk.c
include psutil/arch/windows/disk.h
include psutil/arch/windows/net.c
include psutil/arch/windows/net.h
include psutil/arch/windows/ntextapi.h
include psutil/arch/windows/process_handles.c
include psutil/arch/windows/process_handles.h
include psutil/arch/windows/process_info.c
include psutil/arch/windows/process_info.h
include psutil/arch/windows/process_utils.c
include psutil/arch/windows/process_utils.h
include psutil/arch/windows/security.c
include psutil/arch/windows/security.h
include psutil/arch/windows/services.c
include psutil/arch/windows/services.h
include psutil/arch/windows/socks.c
include psutil/arch/windows/socks.h
include psutil/arch/windows/wmi.c
include psutil/arch/windows/wmi.h
include psutil/tests/README.rst
@ -108,14 +115,15 @@ include scripts/internal/README
include scripts/internal/bench_oneshot.py
include scripts/internal/bench_oneshot_2.py
include scripts/internal/check_broken_links.py
include scripts/internal/download_exes.py
include scripts/internal/clinter.py
include scripts/internal/fix_flake8.py
include scripts/internal/generate_manifest.py
include scripts/internal/print_access_denied.py
include scripts/internal/print_announce.py
include scripts/internal/print_api_speed.py
include scripts/internal/print_timeline.py
include scripts/internal/purge_installation.py
include scripts/internal/scriptutils.py
include scripts/internal/win_download_wheels.py
include scripts/internal/winmake.py
include scripts/iotop.py
include scripts/killall.py

57
third_party/python/psutil/Makefile поставляемый
Просмотреть файл

@ -3,7 +3,7 @@
# You can set the variables below from the command line.
PYTHON = python3
TSCRIPT = psutil/tests/__main__.py
TSCRIPT = psutil/tests/runner.py
ARGS =
# List of nice-to-have dev libs.
DEPS = \
@ -11,20 +11,22 @@ DEPS = \
check-manifest \
coverage \
flake8 \
pyperf \
requests \
setuptools \
twine \
virtualenv \
wheel
PY2_DEPS = \
futures \
ipaddress \
mock==1.0.1 \
perf \
requests \
setuptools \
sphinx \
twine \
unittest2 \
virtualenv \
wheel
unittest2
DEPS += `$(PYTHON) -c \
"import sys; print('$(PY2_DEPS)' if sys.version_info[0] == 2 else '')"`
# In not in a virtualenv, add --user options for install commands.
INSTALL_OPTS = `$(PYTHON) -c "import sys; print('' if hasattr(sys, 'real_prefix') else '--user')"`
INSTALL_OPTS = `$(PYTHON) -c \
"import sys; print('' if hasattr(sys, 'real_prefix') else '--user')"`
TEST_PREFIX = PYTHONWARNINGS=all PSUTIL_TESTING=1 PSUTIL_DEBUG=1
all: test
@ -54,8 +56,7 @@ clean: ## Remove all build files.
build/ \
dist/ \
docs/_build/ \
htmlcov/ \
tmp/
htmlcov/
_:
@ -67,13 +68,11 @@ build: _ ## Compile without installing.
@# "import psutil" when using the interactive interpreter from within
@# this directory.
PYTHONWARNINGS=all $(PYTHON) setup.py build_ext -i
rm -rf tmp
$(PYTHON) -c "import psutil" # make sure it actually worked
install: ## Install this package as current user in "edit" mode.
${MAKE} build
PYTHONWARNINGS=all $(PYTHON) setup.py develop $(INSTALL_OPTS)
rm -rf tmp
uninstall: ## Uninstall this package via pip.
cd ..; $(PYTHON) -m pip uninstall -y -v psutil || true
@ -101,8 +100,8 @@ install-pip: ## Install pip (no-op if already installed).
setup-dev-env: ## Install GIT hooks, pip, test deps (also upgrades them).
${MAKE} install-git-hooks
${MAKE} install-pip
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade pip
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade $(DEPS)
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade --trusted-host files.pythonhosted.org pip
$(PYTHON) -m pip install $(INSTALL_OPTS) --upgrade --trusted-host files.pythonhosted.org $(DEPS)
# ===================================================================
# Tests
@ -154,7 +153,7 @@ test-by-name: ## e.g. make test-by-name ARGS=psutil.tests.test_system.TestSyste
test-failed: ## Re-run tests which failed on last run
${MAKE} install
$(TEST_PREFIX) $(PYTHON) -c "import psutil.tests.runner as r; r.run(last_failed=True)"
$(TEST_PREFIX) $(PYTHON) $(TSCRIPT) --last-failed
test-coverage: ## Run test coverage.
${MAKE} install
@ -170,8 +169,18 @@ test-coverage: ## Run test coverage.
# Linters
# ===================================================================
flake8: ## flake8 linter.
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8
lint-py: ## Run Python (flake8) linter.
@git ls-files '*.py' | xargs $(PYTHON) -m flake8
lint-c: ## Run C linter.
@git ls-files '*.c' '*.h' | xargs $(PYTHON) scripts/internal/clinter.py
lint: ## Run Python (flake8) and C linters.
${MAKE} lint-py
${MAKE} lint-c
fix-lint: ## Attempt to automatically fix some Python lint issues.
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8 --exit-zero | $(PYTHON) scripts/internal/fix_flake8.py
# ===================================================================
# GIT
@ -197,7 +206,7 @@ wheel: ## Generate wheel.
$(PYTHON) setup.py bdist_wheel
win-download-wheels: ## Download wheels hosted on appveyor.
$(TEST_PREFIX) $(PYTHON) scripts/internal/download_exes.py --user giampaolo --project psutil
$(TEST_PREFIX) $(PYTHON) scripts/internal/win_download_wheels.py --user giampaolo --project psutil
upload-src: ## Upload source tarball on https://pypi.org/project/psutil/
${MAKE} sdist
@ -254,10 +263,12 @@ print-timeline: ## Print releases' timeline.
@$(PYTHON) scripts/internal/print_timeline.py
print-access-denied: ## Print AD exceptions
@$(PYTHON) scripts/internal/print_access_denied.py
${MAKE} install
@$(TEST_PREFIX) $(PYTHON) scripts/internal/print_access_denied.py
print-api-speed: ## Benchmark all API calls
@$(PYTHON) scripts/internal/print_api_speed.py $(ARGS)
${MAKE} install
@$(TEST_PREFIX) $(PYTHON) scripts/internal/print_api_speed.py $(ARGS)
# ===================================================================
# Misc

71
third_party/python/psutil/PKG-INFO поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
Metadata-Version: 1.2
Name: psutil
Version: 5.6.3
Version: 5.7.0
Summary: Cross-platform lib for process and system monitoring in Python.
Home-page: https://github.com/giampaolo/psutil
Author: Giampaolo Rodola
@ -8,7 +8,7 @@ Author-email: g.rodola@gmail.com
License: BSD
Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
| |version| |py-versions| |packages| |license|
| |travis| |appveyor| |doc| |twitter| |tidelift|
| |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift|
.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pepy.tech/project/psutil
@ -30,14 +30,18 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
:target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=giampaolo/psutil&amp;utm_campaign=Badge_Grade
:alt: Code quality
.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=linux%20/%20osx
.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=windows
.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD
:target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci
:alt: FreeBSD tests (Cirrus-Ci)
.. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
@ -104,30 +108,36 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy <http://pypy.org/>`__ is also known to work.
...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 <http://pypy.org/>`__ is also known to work.
Professional support
====================
psutil for enterprise
=====================
.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
:width: 100
:width: 150
:alt: Tidelift
:target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
.. list-table::
:widths: 10 100
:widths: 10 150
* - |tideliftlogo|
- Professional support for psutil is available as part of the
`Tidelift Subscription`_.
Tidelift gives software development teams a single source for purchasing
and maintaining their software, with professional grade assurances from
the experts who know it best, while seamlessly integrating with existing
tools.
By subscribing you will help me (`Giampaolo Rodola`_) support psutil
future development. Alternatively consider making a small `donation`_.
- The maintainer of psutil and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the open
source dependencies you use to build your applications. Save time,
reduce risk, and improve code health, while paying the maintainers of
the exact dependencies you use.
`Learn more <https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`__.
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support
psutil future development. Alternatively consider making a small
`donation`_.
Security
========
To report a security vulnerability, please use the `Tidelift security
contact`_. Tidelift will coordinate the fix and disclosure.
Example applications
====================
@ -170,9 +180,7 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
@ -367,7 +375,7 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
@ -393,8 +401,8 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
[popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)]
>>>
>>> p.connections()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
@ -436,6 +444,7 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
>>> p.resume()
>>>
>>> p.terminate()
>>> p.kill()
>>> p.wait(timeout=3)
0
>>>
@ -455,7 +464,7 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
>>> for proc in psutil.process_iter(['pid', 'name']):
... print(proc.info)
...
{'pid': 1, 'name': 'systemd'}
@ -515,6 +524,9 @@ Description: | |downloads| |stars| |forks| |contributors| |coverage| |quality|
.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html
.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
.. _Tidelift security contact: https://tidelift.com/security
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability
Platform: Platform Independent
@ -526,9 +538,16 @@ Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: Microsoft :: Windows :: Windows 7
Classifier: Operating System :: Microsoft :: Windows :: Windows 8
Classifier: Operating System :: Microsoft :: Windows :: Windows 8.1
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2003
Classifier: Operating System :: Microsoft :: Windows :: Windows Server 2008
Classifier: Operating System :: Microsoft :: Windows :: Windows Vista
Classifier: Operating System :: Microsoft
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: AIX
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
Classifier: Operating System :: POSIX :: BSD :: NetBSD
Classifier: Operating System :: POSIX :: BSD :: OpenBSD
@ -547,8 +566,10 @@ Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Benchmark
Classifier: Topic :: System :: Hardware :: Hardware Drivers
Classifier: Topic :: System :: Hardware
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring :: Hardware Watchdog
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Operating System

58
third_party/python/psutil/README.rst поставляемый
Просмотреть файл

@ -1,6 +1,6 @@
| |downloads| |stars| |forks| |contributors| |coverage| |quality|
| |version| |py-versions| |packages| |license|
| |travis| |appveyor| |doc| |twitter| |tidelift|
| |travis| |appveyor| |cirrus| |doc| |twitter| |tidelift|
.. |downloads| image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pepy.tech/project/psutil
@ -22,14 +22,18 @@
:target: https://www.codacy.com/app/g-rodola/psutil?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=giampaolo/psutil&amp;utm_campaign=Badge_Grade
:alt: Code quality
.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=linux%20/%20osx
.. |travis| image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=windows
.. |appveyor| image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. |cirrus| image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD
:target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci
:alt: FreeBSD tests (Cirrus-Ci)
.. |coverage| image:: https://img.shields.io/coveralls/github/giampaolo/psutil.svg?label=test%20coverage
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
@ -96,30 +100,36 @@ psutil currently supports the following platforms:
- **Sun Solaris**
- **AIX**
...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy <http://pypy.org/>`__ is also known to work.
...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy3 <http://pypy.org/>`__ is also known to work.
Professional support
====================
psutil for enterprise
=====================
.. |tideliftlogo| image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
:width: 100
:width: 150
:alt: Tidelift
:target: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
.. list-table::
:widths: 10 100
:widths: 10 150
* - |tideliftlogo|
- Professional support for psutil is available as part of the
`Tidelift Subscription`_.
Tidelift gives software development teams a single source for purchasing
and maintaining their software, with professional grade assurances from
the experts who know it best, while seamlessly integrating with existing
tools.
By subscribing you will help me (`Giampaolo Rodola`_) support psutil
future development. Alternatively consider making a small `donation`_.
- The maintainer of psutil and thousands of other packages are working
with Tidelift to deliver commercial support and maintenance for the open
source dependencies you use to build your applications. Save time,
reduce risk, and improve code health, while paying the maintainers of
the exact dependencies you use.
`Learn more <https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=enterprise&utm_term=repo>`__.
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme
By subscribing to Tidelift you will help me (`Giampaolo Rodola`_) support
psutil future development. Alternatively consider making a small
`donation`_.
Security
========
To report a security vulnerability, please use the `Tidelift security
contact`_. Tidelift will coordinate the fix and disclosure.
Example applications
====================
@ -162,9 +172,7 @@ Portings
- Go: https://github.com/shirou/gopsutil
- C: https://github.com/hamon-in/cpslib
- Node: https://github.com/christkv/node-psutil
- Rust: https://github.com/borntyping/rust-psutil
- Ruby: https://github.com/spacewander/posixpsutil
- Nim: https://github.com/johnscillieri/psutil-nim
@ -359,7 +367,7 @@ Process management
pgids(real=1000, effective=1000, saved=1000)
>>>
>>> p.cpu_times()
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1)
pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1, iowait=0.0)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
@ -385,8 +393,8 @@ Process management
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)]
[popenfile(path='/home/giampaolo/monit.py', fd=3, position=0, mode='r', flags=32768),
popenfile(path='/var/log/monit.log', fd=4, position=235542, mode='a', flags=33793)]
>>>
>>> p.connections()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'),
@ -428,6 +436,7 @@ Process management
>>> p.resume()
>>>
>>> p.terminate()
>>> p.kill()
>>> p.wait(timeout=3)
0
>>>
@ -447,7 +456,7 @@ Further process APIs
.. code-block:: python
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name']):
>>> for proc in psutil.process_iter(['pid', 'name']):
... print(proc.info)
...
{'pid': 1, 'name': 'systemd'}
@ -507,3 +516,6 @@ Windows services
.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html
.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
.. _Tidelift security contact: https://tidelift.com/security
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme

42
third_party/python/psutil/docs/DEVGUIDE.rst поставляемый
Просмотреть файл

@ -1,24 +1,13 @@
Setup and running tests
=======================
Build, setup and running tests
===============================
If you plan on hacking on psutil this is what you're supposed to do first:
- clone the GIT repository:
.. code-block:: bash
$ git clone git@github.com:giampaolo/psutil.git
- install test deps and GIT hooks:
Make sure to `install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`__
a C compiler first, then:
.. code-block:: bash
git clone git@github.com:giampaolo/psutil.git
make setup-dev-env
- run tests:
.. code-block:: bash
make test
- bear in mind that ``make``(see `Makefile`_) is the designated tool to run
@ -47,7 +36,7 @@ Some useful make commands:
make test # run unit tests
make test-memleaks # run memory leak tests
make test-coverage # run test coverage
make flake8 # run PEP8 linter
make lint # run Python (PEP8) and C linters
There are some differences between ``make`` on UNIX and Windows.
For instance, to run a specific Python version. On UNIX:
@ -60,13 +49,7 @@ On Windows:
.. code-block:: bat
set PYTHON=C:\python35\python.exe && make test
...or:
.. code-block:: bat
make -p 35 test
make -p C:\python35\python.exe test
If you want to modify psutil and run a script on the fly which uses it do
(on UNIX):
@ -121,6 +104,7 @@ Make a pull request
- commit your changes: ``git commit -am 'add some feature'``
- push to the branch: ``git push origin new-feature``
- create a new pull request by via github web interface
- remember to update `HISTORY.rst`_ and `CREDITS`_ files.
Continuous integration
======================
@ -141,14 +125,18 @@ Both services run psutil test suite against all supported python version
(2.6 - 3.6).
Two icons in the home page (README) always show the build status:
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20macOS
.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux,%20OSX,%20PyPy
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux and macOS tests (Travis)
:alt: Linux, macOS and PyPy3 tests (Travis)
.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://img.shields.io/cirrus/github/giampaolo/psutil?label=FreeBSD
:target: https://cirrus-ci.com/github/giampaolo/psutil-cirrus-ci
:alt: FreeBSD tests (Cirrus-CI)
BSD, AIX and Solaris are currently tested manually.
Test coverage
@ -200,3 +188,5 @@ These are notes for myself (Giampaolo):
.. _`RsT syntax`: http://docutils.sourceforge.net/docs/user/rst/quickref.htm
.. _`sphinx`: http://sphinx-doc.org
.. _`Travis`: https://travis-ci.org/giampaolo/psuti
.. _`HISTORY.rst`: https://github.com/giampaolo/psutil/blob/master/HISTORY.rst
.. _`CREDITS`: https://github.com/giampaolo/psutil/blob/master/CREDITS

5
third_party/python/psutil/docs/DEVNOTES поставляемый
Просмотреть файл

@ -158,10 +158,11 @@ BUGFIXES
- #600: windows / open_files(): support network file handles.
REJECTED
========
REJECTED IDEAS
==============
- #550: threads per core
- #1667: process_iter(new_only=True)
INCONSISTENCIES
===============

9
third_party/python/psutil/docs/Makefile поставляемый
Просмотреть файл

@ -2,7 +2,7 @@
#
# You can set these variables from the command line.
PYTHON = python
PYTHON = python3
SPHINXOPTS =
SPHINXBUILD = $(PYTHON) -m sphinx
PAPER =
@ -15,6 +15,9 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
DEPS = sphinx
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@ -224,3 +227,7 @@ dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."
.PHONY: setup-dev-env
setup-dev-env: ## Install GIT hooks, pip, test deps (also upgrades them).
$(PYTHON) -m pip install --user --upgrade --trusted-host files.pythonhosted.org $(DEPS)

Просмотреть файл

@ -15,10 +15,30 @@
border-right:10px !important;
}
.local-toc li ul li{
.local-toc li ul li {
padding-left: 20px !important;
}
.rst-content ul p {
margin-bottom: 0px !important;
}
.document td {
padding-bottom: 0px !important;
}
.document th {
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.document th p {
margin-bottom: 0px !important;
}
.document th p {
}
.function .descclassname {
font-weight: normal !important;
}

414
third_party/python/psutil/docs/index.rst поставляемый
Просмотреть файл

@ -13,7 +13,7 @@ Quick links
- `Blog <http://grodola.blogspot.com/search/label/psutil>`__
- `Forum <http://groups.google.com/group/psutil/topics>`__
- `Download <https://pypi.org/project/psutil/#files>`__
- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
- `Development guide <https://github.com/giampaolo/psutil/blob/master/docs/DEVGUIDE.rst>`_
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`__
About
@ -42,21 +42,45 @@ Supported Python versions are **2.6**, **2.7** and **3.4+**.
The psutil documentation you're reading is distributed as a single HTML page.
Professional support
--------------------
.. image:: https://nedbatchelder.com/pix/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
:width: 80px
:align: left
Professional support for psutil is available as part of the `Tidelift Subscription`_.
Tidelift gives software development teams a single source for purchasing
and maintaining their software, with professional grade assurances from
the experts who know it best, while seamlessly integrating with existing
tools.
By subscribing you will help me (`Giampaolo Rodola`_) support psutil
future development. Alternatively consider making a small `donation`_.
To report a security vulnerability, please use the `Tidelift security
contact`_. Tidelift will coordinate the fix and disclosure.
Install
-------
The easiest way to install psutil is via ``pip``::
Linux Ubuntu / Debian::
pip install psutil
sudo apt-get install gcc python3-dev
sudo pip3 install psutil
On UNIX this requires a C compiler (e.g. gcc) installed. On Windows pip will
automatically retrieve a pre-compiled wheel version from
`PyPI repository <https://pypi.org/project/psutil>`__.
Alternatively, see more detailed
Linux Redhat::
sudo yum install gcc python3-devel
sudo pip3 install psutil
Windows::
pip3 install psutil
For other platforms see more detailed
`install <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
instructions.
System related functions
========================
@ -78,7 +102,8 @@ CPU
- **nice** *(UNIX)*: time spent by niced (prioritized) processes executing in
user mode; on Linux this also includes **guest_nice** time
- **iowait** *(Linux)*: time spent waiting for I/O to complete
- **iowait** *(Linux)*: time spent waiting for I/O to complete. This is *not*
accounted in **idle** time counter.
- **irq** *(Linux, BSD)*: time spent for servicing hardware interrupts
- **softirq** *(Linux)*: time spent for servicing software interrupts
- **steal** *(Linux 2.6.11+)*: time spent by other operating systems running
@ -161,8 +186,10 @@ CPU
Return the number of logical CPUs in the system (same as `os.cpu_count`_
in Python 3.4) or ``None`` if undetermined.
If *logical* is ``False`` return the number of physical cores only (hyper
thread CPUs are excluded) or ``None`` if undetermined.
*logical* cores means the number of physical cores multiplied by the number
of threads that can run on each core (this is known as Hyper Threading).
If *logical* is ``False`` return the number of physical cores only (Hyper
Thread CPUs are excluded) or ``None`` if undetermined.
On OpenBSD and NetBSD ``psutil.cpu_count(logical=False)`` always return
``None``.
Example on a system having 2 physical hyper-thread CPU cores:
@ -241,19 +268,27 @@ CPU
.. function:: getloadavg()
Return the average system load over the last 1, 5 and 15 minutes as a tuple.
The load represents how many processes are waiting to be run by the
operating system.
On UNIX systems this relies on `os.getloadavg`_. On Windows this is
emulated by using a Windows API that spawns a thread which updates the
average every 5 seconds, mimicking the UNIX behavior. Thus, the first time
this is called and for the next 5 seconds it will return a meaningless
``(0.0, 0.0, 0.0)`` tuple. Example:
The load represents the processes which are in a runnable state, either
using the CPU or waiting to use the CPU (e.g. waiting for disk I/O).
On UNIX systems this relies on `os.getloadavg`_. On Windows this is emulated
by using a Windows API that spawns a thread which keeps running in
background and updates the load average every 5 seconds, mimicking the UNIX
behavior. Thus, the first time this is called and for the next 5 seconds
it will return a meaningless ``(0.0, 0.0, 0.0)`` tuple.
The numbers returned only make sense if related to the number of CPU cores
installed on the system. So, for instance, `3.14` on a system with 10 CPU
cores means that the system load was 31.4% percent over the last N minutes.
.. code-block:: python
>>> import psutil
>>> psutil.getloadavg()
(3.14, 3.89, 4.67)
>>> psutil.cpu_count()
10
>>> # percentage representation
>>> [x / psutil.cpu_count() * 100 for x in psutil.getloadavg()]
[31.4, 38.9, 46.7]
Availability: Unix, Windows
@ -267,7 +302,7 @@ Memory
Return statistics about system memory usage as a named tuple including the
following fields, expressed in bytes. Main metrics:
- **total**: total physical memory.
- **total**: total physical memory (exclusive swap).
- **available**: the memory that can be given instantly to processes without
the system going into swap.
This is calculated by summing different memory values depending on the
@ -353,7 +388,7 @@ Disks
mount point and filesystem type, similarly to "df" command on UNIX. If *all*
parameter is ``False`` it tries to distinguish and return physical devices
only (e.g. hard disks, cd-rom drives, USB keys) and ignore all others
(e.g. memory partitions such as /dev/shm).
(e.g. pseudo, memory, duplicate, inaccessible filesystems).
Note that this may not be fully reliable on all systems (e.g. on BSD this
parameter is ignored).
Named tuple's **fstype** field is a string which varies depending on the
@ -513,7 +548,8 @@ Network
to obtain a usable socket object.
On Windows and SunOS this is always set to ``-1``.
- **family**: the address family, either `AF_INET`_, `AF_INET6`_ or `AF_UNIX`_.
- **type**: the address type, either `SOCK_STREAM`_ or `SOCK_DGRAM`_.
- **type**: the address type, either `SOCK_STREAM`_, `SOCK_DGRAM`_ or
`SOCK_SEQPACKET`_.
- **laddr**: the local address as a ``(ip, port)`` named tuple or a ``path``
in case of AF_UNIX sockets. For UNIX sockets see notes below.
- **raddr**: the remote address as a ``(ip, port)`` named tuple or an
@ -825,38 +861,24 @@ Functions
Return an iterator yielding a :class:`Process` class instance for all running
processes on the local machine.
Every instance is only created once and then cached into an internal table
which is updated every time an element is yielded.
Cached :class:`Process` instances are checked for identity so that you're
safe in case a PID has been reused by another process, in which case the
cached instance is updated.
This is preferred over :func:`psutil.pids()` for iterating over processes.
Sorting order in which processes are returned is based on their PID.
This should be preferred over :func:`psutil.pids()` to iterate over processes
as it's safe from race condition.
Every :class:`Process` instance is only created once, and then cached for the
next time :func:`psutil.process_iter()` is called (if PID is still alive).
Also it makes sure process PIDs are not reused.
*attrs* and *ad_value* have the same meaning as in :meth:`Process.as_dict()`.
If *attrs* is specified :meth:`Process.as_dict()` is called internally and
the resulting dict is stored as a ``info`` attribute which is attached to the
returned :class:`Process` instances.
If *attrs* is specified :meth:`Process.as_dict()` result will be stored as a
``info`` attribute attached to the returned :class:`Process` instances.
If *attrs* is an empty list it will retrieve all process info (slow).
Example usage::
Sorting order in which processes are returned is based on their PID.
Example::
>>> import psutil
>>> for proc in psutil.process_iter():
... try:
... pinfo = proc.as_dict(attrs=['pid', 'name', 'username'])
... except psutil.NoSuchProcess:
... pass
... else:
... print(pinfo)
...
{'name': 'systemd', 'pid': 1, 'username': 'root'}
{'name': 'kthreadd', 'pid': 2, 'username': 'root'}
{'name': 'ksoftirqd/0', 'pid': 3, 'username': 'root'}
...
More compact version using *attrs* parameter::
>>> import psutil
>>> for proc in psutil.process_iter(attrs=['pid', 'name', 'username']):
>>> for proc in psutil.process_iter(['pid', 'name', 'username']):
... print(proc.info)
...
{'name': 'systemd', 'pid': 1, 'username': 'root'}
@ -864,27 +886,16 @@ Functions
{'name': 'ksoftirqd/0', 'pid': 3, 'username': 'root'}
...
Example of a dict comprehensions to create a ``{pid: info, ...}`` data
structure::
A dict comprehensions to create a ``{pid: info, ...}`` data structure::
>>> import psutil
>>> procs = {p.pid: p.info for p in psutil.process_iter(attrs=['name', 'username'])}
>>> procs = {p.pid: p.info for p in psutil.process_iter(['name', 'username'])}
>>> procs
{1: {'name': 'systemd', 'username': 'root'},
2: {'name': 'kthreadd', 'username': 'root'},
3: {'name': 'ksoftirqd/0', 'username': 'root'},
...}
Example showing how to filter processes by name::
>>> import psutil
>>> [p.info for p in psutil.process_iter(attrs=['pid', 'name']) if 'python' in p.info['name']]
[{'name': 'python3', 'pid': 21947},
{'name': 'python', 'pid': 23835}]
See also `process filtering <#filtering-and-sorting-processes>`__ section for
more examples.
.. versionchanged::
5.3.0 added "attrs" and "ad_value" parameters.
@ -898,11 +909,11 @@ Functions
Convenience function which waits for a list of :class:`Process` instances to
terminate. Return a ``(gone, alive)`` tuple indicating which processes are
gone and which ones are still alive. The *gone* ones will have a new
*returncode* attribute indicating process exit status (will be ``None`` for
processes which are not our children).
*returncode* attribute indicating process exit status as returned by
:meth:`Process.wait`.
``callback`` is a function which gets called when one of the processes being
waited on is terminated and a :class:`Process` instance is passed as callback
argument).
argument (the instance will also have a *returncode* attribute set).
This function will return as soon as all processes terminate or when
*timeout* (seconds) occurs.
Differently from :meth:`Process.wait` it will not raise
@ -1069,9 +1080,9 @@ Process class
+------------------------------+-------------------------------+------------------------------+------------------------------+--------------------------+--------------------------+
| :meth:`gids` | | :meth:`name` | :meth:`num_ctx_switches` | :meth:`terminal` | :meth:`terminal` |
+------------------------------+-------------------------------+------------------------------+------------------------------+--------------------------+--------------------------+
| :meth:`num_ctx_switches` | | :meth:`ppid` | :meth:`ppid` | | |
| :meth:`num_ctx_switches` | :meth:`exe` | :meth:`ppid` | :meth:`ppid` | | |
+------------------------------+-------------------------------+------------------------------+------------------------------+--------------------------+--------------------------+
| :meth:`num_threads` | | :meth:`status` | :meth:`status` | :meth:`gids` | :meth:`gids` |
| :meth:`num_threads` | :meth:`name` | :meth:`status` | :meth:`status` | :meth:`gids` | :meth:`gids` |
+------------------------------+-------------------------------+------------------------------+------------------------------+--------------------------+--------------------------+
| :meth:`uids` | | :meth:`terminal` | :meth:`terminal` | :meth:`uids` | :meth:`uids` |
+------------------------------+-------------------------------+------------------------------+------------------------------+--------------------------+--------------------------+
@ -1205,6 +1216,8 @@ Process class
The process current working directory as an absolute path.
.. versionchanged:: 5.6.4 added support for NetBSD
.. method:: username()
The name of the user that owns the process. On UNIX this is calculated by
@ -1287,13 +1300,15 @@ Process class
Here's an example on how to set the highest I/O priority depending on what
platform you're on::
import psutil
p = psutil.Process()
if psutil.LINUX
p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
else: # Windows
p.ionice(psutil.IOPRIO_HIGH)
p.ionice() # get
>>> import psutil
>>> p = psutil.Process()
>>> if psutil.LINUX:
... p.ionice(psutil.IOPRIO_CLASS_RT, value=7)
... else:
... p.ionice(psutil.IOPRIO_HIGH)
...
>>> p.ionice() # get
pionice(ioclass=<IOPriority.IOPRIO_CLASS_RT: 1>, value=7)
Availability: Linux, Windows Vista+
@ -1401,16 +1416,33 @@ Process class
.. method:: cpu_times()
Return a `(user, system, children_user, children_system)` named tuple
representing the accumulated process time, in seconds (see
`explanation <http://stackoverflow.com/questions/556405/>`__).
On Windows and macOS only *user* and *system* are filled, the others are
set to ``0``.
Return a named tuple representing the accumulated process times, in seconds
(see `explanation <http://stackoverflow.com/questions/556405/>`__).
This is similar to `os.times`_ but can be used for any process PID.
- **user**: time spent in user mode.
- **system**: time spent in kernel mode.
- **children_user**: user time of all child processes (always ``0`` on
Windows and macOS).
- **system_user**: user time of all child processes (always ``0`` on
Windows and macOS).
- **iowait**: (Linux) time spent waiting for blocking I/O to complete.
This value is excluded from `user` and `system` times count (because the
CPU is not doing any work).
>>> import psutil
>>> p = psutil.Process()
>>> p.cpu_times()
pcputimes(user=0.03, system=0.67, children_user=0.0, children_system=0.0, iowait=0.08)
>>> sum(p.cpu_times()[:2]) # cumulative, excluding children and iowait
0.70
.. versionchanged::
4.1.0 return two extra fields: *children_user* and *children_system*.
.. versionchanged::
5.6.4 added *iowait* on Linux.
.. method:: cpu_percent(interval=None)
Return a float representing the process CPU utilization as a percentage
@ -1752,13 +1784,12 @@ Process class
on Windows this method is not reliable due to some limitations of the
underlying Windows API which may hang when retrieving certain file
handles.
In order to work around that psutil spawns a thread for each handle and
kills it if it's not responding after 100ms.
In order to work around that psutil spawns a thread to determine the file
handle name and kills it if it's not responding after 100ms.
That implies that this method on Windows is not guaranteed to enumerate
all regular file handles (see
`issue 597 <https://github.com/giampaolo/psutil/pull/597>`_).
Also, it will only list files living in the C:\\ drive (see
`issue 1020 <https://github.com/giampaolo/psutil/pull/1020>`_).
Tools like ProcessHacker has the same limitation.
.. warning::
on BSD this method can return files with a null path ("") due to a
@ -1782,7 +1813,8 @@ Process class
always set to ``-1``.
- **family**: the address family, either `AF_INET`_, `AF_INET6`_ or
`AF_UNIX`_.
- **type**: the address type, either `SOCK_STREAM`_ or `SOCK_DGRAM`_.
- **type**: the address type, either `SOCK_STREAM`_, `SOCK_DGRAM`_ or
`SOCK_SEQPACKET`_. .
- **laddr**: the local address as a ``(ip, port)`` named tuple or a ``path``
in case of AF_UNIX sockets. For UNIX sockets see notes below.
- **raddr**: the remote address as a ``(ip, port)`` named tuple or an
@ -2189,7 +2221,7 @@ Process priority constants
.. data:: IOPRIO_NORMAL
.. data:: IOPRIO_HIGH
A set of integers representing the I/O priority of a process on Linux.
A set of integers representing the I/O priority of a process on Windows.
They can be used in conjunction with :meth:`psutil.Process.ionice()` to get
or set process I/O priority.
@ -2291,46 +2323,6 @@ Hardware constants
>>> if psutil.version_info >= (4, 5):
... pass
----
Unicode
=======
Starting from version 5.3.0 psutil adds unicode support, see `issue #1040`_.
The notes below apply to *any* API returning a string such as
:meth:`Process.exe` or :meth:`Process.cwd`, including non-filesystem related
methods such as :meth:`Process.username` or :meth:`WindowsService.description`:
* all strings are encoded by using the OS filesystem encoding
(``sys.getfilesystemencoding()``) which varies depending on the platform
(e.g. "UTF-8" on macOS, "mbcs" on Win)
* no API call is supposed to crash with ``UnicodeDecodeError``
* instead, in case of badly encoded data returned by the OS, the following error handlers are used to replace the corrupted characters in the string:
* Python 3: ``sys.getfilesystemencodeerrors()`` (PY 3.6+) or
``"surrogatescape"`` on POSIX and ``"replace"`` on Windows
* Python 2: ``"replace"``
* on Python 2 all APIs return bytes (``str`` type), never ``unicode``
* on Python 2, you can go back to ``unicode`` by doing:
.. code-block:: python
>>> unicode(p.exe(), sys.getdefaultencoding(), errors="replace")
Example which filters processes with a funky name working with both Python 2
and 3::
# -*- coding: utf-8 -*-
import psutil, sys
PY3 = sys.version_info[0] == 2
LOOKFOR = u"ƒőő"
for proc in psutil.process_iter(attrs=['name']):
name = proc.info['name']
if not PY3:
name = unicode(name, sys.getdefaultencoding(), errors="replace")
if LOOKFOR == name:
print("process %s found" % p)
Recipes
=======
@ -2346,7 +2338,7 @@ Check string against :meth:`Process.name()`:
def find_procs_by_name(name):
"Return a list of processes matching 'name'."
ls = []
for p in psutil.process_iter(attrs=['name']):
for p in psutil.process_iter(['name']):
if p.info['name'] == name:
ls.append(p)
return ls
@ -2362,7 +2354,7 @@ A bit more advanced, check string against :meth:`Process.name()`,
def find_procs_by_name(name):
"Return a list of processes matching 'name'."
ls = []
for p in psutil.process_iter(attrs=["name", "exe", "cmdline"]):
for p in psutil.process_iter(["name", "exe", "cmdline"]):
if name == p.info['name'] or \
p.info['exe'] and os.path.basename(p.info['exe']) == name or \
p.info['cmdline'] and p.info['cmdline'][0] == name:
@ -2396,83 +2388,34 @@ Kill process tree
callback=on_terminate)
return (gone, alive)
Terminate my children
---------------------
This may be useful in unit tests whenever sub-processes are started.
This will help ensure that no extra children (zombies) stick around to hog
resources.
::
import psutil
def reap_children(timeout=3):
"Tries hard to terminate and ultimately kill all the children of this process."
def on_terminate(proc):
print("process {} terminated with exit code {}".format(proc, proc.returncode))
procs = psutil.Process().children()
# send SIGTERM
for p in procs:
try:
p.terminate()
except psutil.NoSuchProcess:
pass
gone, alive = psutil.wait_procs(procs, timeout=timeout, callback=on_terminate)
if alive:
# send SIGKILL
for p in alive:
print("process {} survived SIGTERM; trying SIGKILL" % p)
try:
p.kill()
except psutil.NoSuchProcess:
pass
gone, alive = psutil.wait_procs(alive, timeout=timeout, callback=on_terminate)
if alive:
# give up
for p in alive:
print("process {} survived SIGKILL; giving up" % p)
Filtering and sorting processes
-------------------------------
This is a collection of one-liners showing how to use :func:`process_iter()` in
order to filter for processes and sort them.
Setup::
A collection of code samples showing how to use :func:`process_iter()` to filter processes and sort them. Setup::
>>> import psutil
>>> from pprint import pprint as pp
Processes having "python" in their name::
>>> pp([p.info for p in psutil.process_iter(attrs=['pid', 'name']) if 'python' in p.info['name']])
[{'name': 'python3', 'pid': 21947},
{'name': 'python', 'pid': 23835}]
Processes owned by user::
>>> import getpass
>>> pp([(p.pid, p.info['name']) for p in psutil.process_iter(attrs=['name', 'username']) if p.info['username'] == getpass.getuser()])
>>> pp([(p.pid, p.info['name']) for p in psutil.process_iter(['name', 'username']) if p.info['username'] == getpass.getuser()])
(16832, 'bash'),
(19772, 'ssh'),
(20492, 'python')]
Processes actively running::
>>> pp([(p.pid, p.info) for p in psutil.process_iter(attrs=['name', 'status']) if p.info['status'] == psutil.STATUS_RUNNING])
>>> pp([(p.pid, p.info) for p in psutil.process_iter(['name', 'status']) if p.info['status'] == psutil.STATUS_RUNNING])
[(1150, {'name': 'Xorg', 'status': 'running'}),
(1776, {'name': 'unity-panel-service', 'status': 'running'}),
(20492, {'name': 'python', 'status': 'running'})]
Processes using log files::
>>> import os
>>> import psutil
>>> for p in psutil.process_iter(attrs=['name', 'open_files']):
>>> for p in psutil.process_iter(['name', 'open_files']):
... for file in p.info['open_files'] or []:
... if os.path.splitext(file.path)[1] == '.log':
... if file.path.endswith('.log'):
... print("%-5s %-10s %s" % (p.pid, p.info['name'][:10], file.path))
...
1510 upstart /home/giampaolo/.cache/upstart/unity-settings-daemon.log
@ -2481,39 +2424,18 @@ Processes using log files::
Processes consuming more than 500M of memory::
>>> pp([(p.pid, p.info['name'], p.info['memory_info'].rss) for p in psutil.process_iter(attrs=['name', 'memory_info']) if p.info['memory_info'].rss > 500 * 1024 * 1024])
>>> pp([(p.pid, p.info['name'], p.info['memory_info'].rss) for p in psutil.process_iter(['name', 'memory_info']) if p.info['memory_info'].rss > 500 * 1024 * 1024])
[(2650, 'chrome', 532324352),
(3038, 'chrome', 1120088064),
(21915, 'sublime_text', 615407616)]
Top 3 most memory consuming processes::
>>> pp([(p.pid, p.info) for p in sorted(psutil.process_iter(attrs=['name', 'memory_percent']), key=lambda p: p.info['memory_percent'])][-3:])
[(21915, {'memory_percent': 3.6815453247662737, 'name': 'sublime_text'}),
(3038, {'memory_percent': 6.732935429979187, 'name': 'chrome'}),
(3249, {'memory_percent': 8.994554843376399, 'name': 'chrome'})]
Top 3 processes which consumed the most CPU time::
>>> pp([(p.pid, p.info['name'], sum(p.info['cpu_times'])) for p in sorted(psutil.process_iter(attrs=['name', 'cpu_times']), key=lambda p: sum(p.info['cpu_times'][:2]))][-3:])
>>> pp([(p.pid, p.info['name'], sum(p.info['cpu_times'])) for p in sorted(psutil.process_iter(['name', 'cpu_times']), key=lambda p: sum(p.info['cpu_times'][:2]))][-3:])
[(2721, 'chrome', 10219.73),
(1150, 'Xorg', 11116.989999999998),
(2650, 'chrome', 18451.97)]
Top 3 processes which caused the most I/O::
>>> pp([(p.pid, p.info['name']) for p in sorted(psutil.process_iter(attrs=['name', 'io_counters']), key=lambda p: p.info['io_counters'] and p.info['io_counters'][:2])][-3:])
[(21915, 'sublime_text'),
(1871, 'pulseaudio'),
(1510, 'upstart')]
Top 3 processes opening more file descriptors::
>>> pp([(p.pid, p.info) for p in sorted(psutil.process_iter(attrs=['name', 'num_fds']), key=lambda p: p.info['num_fds'])][-3:])
[(21915, {'name': 'sublime_text', 'num_fds': 105}),
(2721, {'name': 'chrome', 'num_fds': 185}),
(2650, {'name': 'chrome', 'num_fds': 354})]
Bytes conversion
----------------
@ -2546,28 +2468,6 @@ Bytes conversion
100399730688
93.5G
Supported platforms
===================
These are the platforms I develop and test on:
* Linux Ubuntu 16.04
* MacOS 10.11 El Captain
* Windows 10
* Solaris 10
* FreeBSD 11
* OpenBSD 6.4
* NetBSD 8.0
* AIX 6.1 TL8 (maintainer `Arnon Yaari <https://github.com/wiggin15>`__)
Earlier versions are supposed to work but are not tested.
For Linux, Windows and MacOS we have continuos integration. Other platforms
are tested manually from time to time.
Oldest supported Windows version is Windows XP, which can be compiled from
sources. Latest wheel supporting Windows XP is
`psutil 2.1.3 <https://pypi.org/project/psutil/2.1.3/#files>`__.
Supported Python versions are 3.4+, 2.7 and 2.6.
FAQs
====
@ -2576,7 +2476,7 @@ FAQs
especially on macOS (see `issue #883`_) and Windows.
Unfortunately there's not much you can do about this except running the
Python process with higher privileges.
On Unix you may run the the Python process as root or use the SUID bit
On Unix you may run the Python process as root or use the SUID bit
(this is the trick used by tools such as ``ps`` and ``netstat``).
On Windows you may run the Python process as NT AUTHORITY\\SYSTEM or install
the Python script as a Windows service (this is the trick used by tools
@ -2585,25 +2485,58 @@ FAQs
Running tests
=============
There are two ways of running tests. If psutil is already installed use::
::
$ python -m psutil.tests
You can use this method as a quick way to make sure psutil fully works on your
platform. If you have a copy of the source code you can also use::
$ make test
$ python3 -m psutil.tests
Development guide
=================
If you plan on hacking on psutil (e.g. want to add a new feature or fix a bug)
If you want to hacking on psutil (e.g. want to add a new feature or fix a bug)
take a look at the `development guide`_.
Platforms support history
=========================
* psutil 5.7.0 (2020-02): drop Windows XP & Server 2003 support
* psutil 5.7.0 (2020-02): **PyPy** on Windows
* psutil 5.4.0 (2017-11): **AIX**
* psutil 3.4.1 (2016-01): **NetBSD**
* psutil 3.3.0 (2015-11): **OpenBSD**
* psutil 1.0.0 (2013-07): **Solaris**
* psutil 0.1.1 (2009-03): **FreeBSD**
* psutil 0.1.0 (2009-01): **Linux, Windows, macOS**
Supported Python versions are 2.6, 2.7, 3.4+ and PyPy3.
Timeline
========
- 2019-0426:
- 2020-02-18:
`5.7.0 <https://pypi.org/project/psutil/5.7.0/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#570>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.7...release-5.7.0#files_bucket>`__
- 2019-11-26:
`5.6.7 <https://pypi.org/project/psutil/5.6.7/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#567>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.6...release-5.6.7#files_bucket>`__
- 2019-11-25:
`5.6.6 <https://pypi.org/project/psutil/5.6.6/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#566>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.5...release-5.6.6#files_bucket>`__
- 2019-11-06:
`5.6.5 <https://pypi.org/project/psutil/5.6.5/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#565>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.4...release-5.6.5#files_bucket>`__
- 2019-11-04:
`5.6.4 <https://pypi.org/project/psutil/5.6.4/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#564>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.3...release-5.6.4#files_bucket>`__
- 2019-06-11:
`5.6.3 <https://pypi.org/project/psutil/5.6.3/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#563>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.2...release-5.6.3#files_bucket>`__
- 2019-04-26:
`5.6.2 <https://pypi.org/project/psutil/5.6.2/#files>`__ -
`what's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst#562>`__ -
`diff <https://github.com/giampaolo/psutil/compare/release-5.6.1...release-5.6.2#files_bucket>`__
@ -2902,13 +2835,15 @@ Timeline
.. _`BPO-6973`: https://bugs.python.org/issue6973
.. _`CPU affinity`: https://www.linuxjournal.com/article/6799?page=0,0
.. _`cpu_distribution.py`: https://github.com/giampaolo/psutil/blob/master/scripts/cpu_distribution.py
.. _`development guide`: https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst
.. _`development guide`: https://github.com/giampaolo/psutil/blob/master/docs/DEVGUIDE.rst
.. _`disk_usage.py`: https://github.com/giampaolo/psutil/blob/master/scripts/disk_usage.py
.. _`donation`: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8
.. _`enums`: https://docs.python.org/3/library/enum.html#module-enum
.. _`fans.py`: https://github.com/giampaolo/psutil/blob/master/scripts/fans.py
.. _`GetDriveType`: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypea
.. _`getfsstat`: http://www.manpagez.com/man/2/getfsstat/
.. _`GetPriorityClass`: https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getpriorityclass
.. _`Giampaolo Rodola`: http://grodola.blogspot.com/p/about.html
.. _`hash`: https://docs.python.org/3/library/functions.html#hash
.. _`ifconfig.py`: https://github.com/giampaolo/psutil/blob/master/scripts/ifconfig.py
.. _`ioprio_get`: https://linux.die.net/man/2/ioprio_get
@ -2919,7 +2854,7 @@ Timeline
.. _`issue #883`: https://github.com/giampaolo/psutil/issues/883
.. _`man prlimit`: https://linux.die.net/man/2/prlimit
.. _`meminfo.py`: https://github.com/giampaolo/psutil/blob/master/scripts/meminfo.py
.. _`netstat.py`: https://github.com/giampaolo/psutil/blob/master/scripts/netstat.py.
.. _`netstat.py`: https://github.com/giampaolo/psutil/blob/master/scripts/netstat.py
.. _`nettop.py`: https://github.com/giampaolo/psutil/blob/master/scripts/nettop.py
.. _`open`: https://docs.python.org/3/library/functions.html#open
.. _`os.cpu_count`: https://docs.python.org/3/library/os.html#os.cpu_count
@ -2944,8 +2879,11 @@ Timeline
.. _`shutil.disk_usage`: https://docs.python.org/3/library/shutil.html#shutil.disk_usage.
.. _`signal module`: https://docs.python.org//library/signal.html
.. _`SOCK_DGRAM`: https://docs.python.org/3/library/socket.html#socket.SOCK_DGRAM
.. _`SOCK_SEQPACKET`: https://docs.python.org/3/library/socket.html#socket.SOCK_SEQPACKET
.. _`SOCK_STREAM`: https://docs.python.org/3/library/socket.html#socket.SOCK_STREAM
.. _`socket.fromfd`: https://docs.python.org/3/library/socket.html#socket.fromfd
.. _`subprocess.Popen`: https://docs.python.org/3/library/subprocess.html#subprocess.Popen
.. _`temperatures.py`: https://github.com/giampaolo/psutil/blob/master/scripts/temperatures.py
.. _`TerminateProcess`: https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-terminateprocess
.. _Tidelift security contact: https://tidelift.com/security
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-psutil?utm_source=pypi-psutil&utm_medium=referral&utm_campaign=readme

6
third_party/python/psutil/make.bat поставляемый
Просмотреть файл

@ -20,15 +20,15 @@ rem set PYTHON=C:\Python34\python.exe & set TSCRIPT=foo.py & make.bat test
rem ==========================================================================
if "%PYTHON%" == "" (
if exist "C:\Python37\python.exe" (
set PYTHON=C:\Python37\python.exe
if exist "C:\Python38-64\python.exe" (
set PYTHON=C:\Python38-64\python.exe
) else (
set PYTHON=C:\Python27\python.exe
)
)
if "%TSCRIPT%" == "" (
set TSCRIPT=psutil\tests\__main__.py
set TSCRIPT=psutil\tests\runner.py
)
rem Needed to locate the .pypirc file and upload exes on PyPI.

154
third_party/python/psutil/psutil/__init__.py поставляемый
Просмотреть файл

@ -25,7 +25,6 @@ from __future__ import division
import collections
import contextlib
import datetime
import errno
import functools
import os
import signal
@ -39,11 +38,18 @@ except ImportError:
pwd = None
from . import _common
from ._common import AccessDenied
from ._common import deprecated_method
from ._common import Error
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import TimeoutExpired
from ._common import wrap_numbers as _wrap_numbers
from ._common import ZombieProcess
from ._compat import long
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3 as _PY3
from ._common import STATUS_DEAD
@ -221,7 +227,7 @@ __all__ = [
__all__.extend(_psplatform.__extra__all__)
__author__ = "Giampaolo Rodola'"
__version__ = "5.6.3"
__version__ = "5.7.0"
version_info = tuple([int(num) for num in __version__.split('.')])
_timer = getattr(time, 'monotonic', time.time)
@ -253,112 +259,6 @@ if (int(__version__.replace('.', '')) !=
raise ImportError(msg)
# =====================================================================
# --- Exceptions
# =====================================================================
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
def __init__(self, msg=""):
Exception.__init__(self, msg)
self.msg = msg
def __repr__(self):
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
return ret.strip()
__str__ = __repr__
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists.
"""
def __init__(self, pid, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
class ZombieProcess(NoSuchProcess):
"""Exception raised when querying a zombie process. This is
raised on macOS, BSD and Solaris only, and not always: depending
on the query the OS may be able to succeed anyway.
On Linux all zombie processes are querable (hence this is never
raised). Windows doesn't have zombie processes.
"""
def __init__(self, pid, name=None, ppid=None, msg=None):
NoSuchProcess.__init__(self, msg)
self.pid = pid
self.ppid = ppid
self.name = name
self.msg = msg
if msg is None:
args = ["pid=%s" % pid]
if name:
args.append("name=%s" % repr(self.name))
if ppid:
args.append("ppid=%s" % self.ppid)
details = "(%s)" % ", ".join(args)
self.msg = "process still exists but it's a zombie " + details
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
def __init__(self, pid=None, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
def __init__(self, seconds, pid=None, name=None):
Error.__init__(self, "timeout after %s seconds" % seconds)
self.seconds = seconds
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg += " (pid=%s)" % self.pid
# Push exception classes into platform specific module namespace.
_psplatform.NoSuchProcess = NoSuchProcess
_psplatform.ZombieProcess = ZombieProcess
_psplatform.AccessDenied = AccessDenied
_psplatform.TimeoutExpired = TimeoutExpired
if POSIX:
from . import _psposix
_psposix.TimeoutExpired = TimeoutExpired
# =====================================================================
# --- Utils
# =====================================================================
@ -875,7 +775,7 @@ class Process(object):
"""
return self._proc.io_counters()
# Linux and Windows >= Vista only
# Linux and Windows
if hasattr(_psplatform.Process, "ionice_get"):
def ionice(self, ioclass=None, value=None):
@ -1290,18 +1190,16 @@ class Process(object):
"calling process (os.getpid()) instead of PID 0")
try:
os.kill(self.pid, sig)
except OSError as err:
if err.errno == errno.ESRCH:
if OPENBSD and pid_exists(self.pid):
# We do this because os.kill() lies in case of
# zombie processes.
raise ZombieProcess(self.pid, self._name, self._ppid)
else:
self._gone = True
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
except ProcessLookupError:
if OPENBSD and pid_exists(self.pid):
# We do this because os.kill() lies in case of
# zombie processes.
raise ZombieProcess(self.pid, self._name, self._ppid)
else:
self._gone = True
raise NoSuchProcess(self.pid, self._name)
except PermissionError:
raise AccessDenied(self.pid, self._name)
@_assert_pid_not_reused
def send_signal(self, sig):
@ -1313,16 +1211,7 @@ class Process(object):
if POSIX:
self._send_signal(sig)
else: # pragma: no cover
if sig == signal.SIGTERM:
self._proc.kill()
# py >= 2.7
elif sig in (getattr(signal, "CTRL_C_EVENT", object()),
getattr(signal, "CTRL_BREAK_EVENT", object())):
self._proc.send_signal(sig)
else:
raise ValueError(
"only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
"are supported on Windows")
self._proc.send_signal(sig)
@_assert_pid_not_reused
def suspend(self):
@ -1370,6 +1259,8 @@ class Process(object):
def wait(self, timeout=None):
"""Wait for process to terminate and, if process is a children
of os.getpid(), also return its exit code, else None.
On Windows there's no such limitation (exit code is always
returned).
If the process is already terminated immediately return None
instead of raising NoSuchProcess.
@ -1634,6 +1525,7 @@ def wait_procs(procs, timeout=None, callback=None):
pass
else:
if returncode is not None or not proc.is_running():
# Set new Process instance attribute.
proc.returncode = returncode
gone.add(proc)
if callback is not None:

236
third_party/python/psutil/psutil/_common.py поставляемый
Просмотреть файл

@ -7,7 +7,7 @@
# Note: this module is imported by setup.py so it should not import
# psutil or third-party modules.
from __future__ import division
from __future__ import division, print_function
import contextlib
import errno
@ -23,6 +23,7 @@ from collections import namedtuple
from socket import AF_INET
from socket import SOCK_DGRAM
from socket import SOCK_STREAM
try:
from socket import AF_INET6
except ImportError:
@ -37,14 +38,14 @@ if sys.version_info >= (3, 4):
else:
enum = None
# can't take it from _common.py as this script is imported by setup.py
PY3 = sys.version_info[0] == 3
__all__ = [
# constants
# OS constants
'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX',
'SUNOS', 'WINDOWS',
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
# connection constants
'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED',
'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN',
@ -56,6 +57,8 @@ __all__ = [
'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED',
'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL',
'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED',
# other constants
'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
# named tuples
'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile',
'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart',
@ -64,7 +67,9 @@ __all__ = [
'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize',
'parse_environ_block', 'path_exists_strict', 'usage_percent',
'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers",
'bytes2human',
'bytes2human', 'conn_to_ntuple', 'debug',
# shell utils
'hilite', 'term_supports_colors', 'print_color',
]
@ -257,7 +262,109 @@ if AF_UNIX is not None:
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
})
del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
# =====================================================================
# --- Exceptions
# =====================================================================
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
__module__ = 'psutil'
def __init__(self, msg=""):
Exception.__init__(self, msg)
self.msg = msg
def __repr__(self):
ret = "psutil.%s %s" % (self.__class__.__name__, self.msg)
return ret.strip()
__str__ = __repr__
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists.
"""
__module__ = 'psutil'
def __init__(self, pid, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
def __path__(self):
return 'xxx'
class ZombieProcess(NoSuchProcess):
"""Exception raised when querying a zombie process. This is
raised on macOS, BSD and Solaris only, and not always: depending
on the query the OS may be able to succeed anyway.
On Linux all zombie processes are querable (hence this is never
raised). Windows doesn't have zombie processes.
"""
__module__ = 'psutil'
def __init__(self, pid, name=None, ppid=None, msg=None):
NoSuchProcess.__init__(self, msg)
self.pid = pid
self.ppid = ppid
self.name = name
self.msg = msg
if msg is None:
args = ["pid=%s" % pid]
if name:
args.append("name=%s" % repr(self.name))
if ppid:
args.append("ppid=%s" % self.ppid)
details = "(%s)" % ", ".join(args)
self.msg = "process still exists but it's a zombie " + details
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
__module__ = 'psutil'
def __init__(self, pid=None, name=None, msg=None):
Error.__init__(self, msg)
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
__module__ = 'psutil'
def __init__(self, seconds, pid=None, name=None):
Error.__init__(self, "timeout after %s seconds" % seconds)
self.seconds = seconds
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg += " (pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg += " (pid=%s)" % self.pid
# ===================================================================
@ -268,12 +375,12 @@ del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
def usage_percent(used, total, round_=None):
"""Calculate percentage usage of 'used' against 'total'."""
try:
ret = (used / total) * 100
ret = (float(used) / total) * 100
except ZeroDivisionError:
ret = 0.0 if isinstance(used, float) or isinstance(total, float) else 0
if round_ is not None:
return round(ret, round_)
return 0.0
else:
if round_ is not None:
ret = round(ret, round_)
return ret
@ -447,7 +554,7 @@ def sockfam_to_enum(num):
else: # pragma: no cover
try:
return socket.AddressFamily(num)
except (ValueError, AttributeError):
except ValueError:
return num
@ -459,11 +566,30 @@ def socktype_to_enum(num):
return num
else: # pragma: no cover
try:
return socket.AddressType(num)
except (ValueError, AttributeError):
return socket.SocketKind(num)
except ValueError:
return num
def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None):
"""Convert a raw connection tuple to a proper ntuple."""
if fam in (socket.AF_INET, AF_INET6):
if laddr:
laddr = addr(*laddr)
if raddr:
raddr = addr(*raddr)
if type_ == socket.SOCK_STREAM and fam in (AF_INET, AF_INET6):
status = status_map.get(status, CONN_NONE)
else:
status = CONN_NONE # ignore whatever C returned to us
fam = sockfam_to_enum(fam)
type_ = socktype_to_enum(type_)
if pid is None:
return pconn(fd, fam, type_, laddr, raddr, status)
else:
return sconn(fd, fam, type_, laddr, raddr, status, pid)
def deprecated_method(replacement):
"""A decorator which can be used to mark a method as deprecated
'replcement' is the method name which will be called instead.
@ -632,3 +758,89 @@ if PY3:
else:
def decode(s):
return s
# =====================================================================
# --- shell utils
# =====================================================================
@memoize
def term_supports_colors(file=sys.stdout):
if os.name == 'nt':
return True
try:
import curses
assert file.isatty()
curses.setupterm()
assert curses.tigetnum("colors") > 0
except Exception:
return False
else:
return True
def hilite(s, color="green", bold=False):
"""Return an highlighted version of 'string'."""
if not term_supports_colors():
return s
attr = []
colors = dict(green='32', red='91', brown='33')
colors[None] = '29'
try:
color = colors[color]
except KeyError:
raise ValueError("invalid color %r; choose between %s" % (
list(colors.keys())))
attr.append(color)
if bold:
attr.append('1')
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s)
def print_color(s, color="green", bold=False, file=sys.stdout):
"""Print a colorized version of string."""
if not term_supports_colors():
print(s, file=file)
elif POSIX:
print(hilite(s, color, bold), file=file)
else:
import ctypes
DEFAULT_COLOR = 7
GetStdHandle = ctypes.windll.Kernel32.GetStdHandle
SetConsoleTextAttribute = \
ctypes.windll.Kernel32.SetConsoleTextAttribute
colors = dict(green=2, red=4, brown=6)
colors[None] = DEFAULT_COLOR
try:
color = colors[color]
except KeyError:
raise ValueError("invalid color %r; choose between %r" % (
color, list(colors.keys())))
if bold and color <= 7:
color += 8
handle_id = -12 if file is sys.stderr else -11
GetStdHandle.restype = ctypes.c_ulong
handle = GetStdHandle(handle_id)
SetConsoleTextAttribute(handle, color)
try:
print(s, file=file)
finally:
SetConsoleTextAttribute(handle, DEFAULT_COLOR)
if bool(os.getenv('PSUTIL_DEBUG', 0)):
import inspect
def debug(msg):
"""If PSUTIL_DEBUG env var is set, print a debug message to stderr."""
fname, lineno, func_name, lines, index = inspect.getframeinfo(
inspect.currentframe().f_back)
print("psutil-debug [%s:%s]> %s" % (fname, lineno, msg),
file=sys.stderr)
else:
def debug(msg):
pass

85
third_party/python/psutil/psutil/_compat.py поставляемый
Просмотреть файл

@ -5,12 +5,15 @@
"""Module which provides compatibility with older Python versions."""
import collections
import errno
import functools
import os
import sys
__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b",
"lru_cache", "which", "get_terminal_size"]
"lru_cache", "which", "get_terminal_size",
"FileNotFoundError", "PermissionError", "ProcessLookupError",
"InterruptedError", "ChildProcessError", "FileExistsError"]
PY3 = sys.version_info[0] == 3
@ -38,6 +41,86 @@ else:
return s
# --- exceptions
if PY3:
FileNotFoundError = FileNotFoundError # NOQA
PermissionError = PermissionError # NOQA
ProcessLookupError = ProcessLookupError # NOQA
InterruptedError = InterruptedError # NOQA
ChildProcessError = ChildProcessError # NOQA
FileExistsError = FileExistsError # NOQA
else:
# https://github.com/PythonCharmers/python-future/blob/exceptions/
# src/future/types/exceptions/pep3151.py
import platform
_singleton = object()
def instance_checking_exception(base_exception=Exception):
def wrapped(instance_checker):
class TemporaryClass(base_exception):
def __init__(self, *args, **kwargs):
if len(args) == 1 and isinstance(args[0], TemporaryClass):
unwrap_me = args[0]
for attr in dir(unwrap_me):
if not attr.startswith('__'):
setattr(self, attr, getattr(unwrap_me, attr))
else:
super(TemporaryClass, self).__init__(*args, **kwargs)
class __metaclass__(type):
def __instancecheck__(cls, inst):
return instance_checker(inst)
def __subclasscheck__(cls, classinfo):
value = sys.exc_info()[1]
return isinstance(value, cls)
TemporaryClass.__name__ = instance_checker.__name__
TemporaryClass.__doc__ = instance_checker.__doc__
return TemporaryClass
return wrapped
@instance_checking_exception(EnvironmentError)
def FileNotFoundError(inst):
return getattr(inst, 'errno', _singleton) == errno.ENOENT
@instance_checking_exception(EnvironmentError)
def ProcessLookupError(inst):
return getattr(inst, 'errno', _singleton) == errno.ESRCH
@instance_checking_exception(EnvironmentError)
def PermissionError(inst):
return getattr(inst, 'errno', _singleton) in (
errno.EACCES, errno.EPERM)
@instance_checking_exception(EnvironmentError)
def InterruptedError(inst):
return getattr(inst, 'errno', _singleton) == errno.EINTR
@instance_checking_exception(EnvironmentError)
def ChildProcessError(inst):
return getattr(inst, 'errno', _singleton) == errno.ECHILD
@instance_checking_exception(EnvironmentError)
def FileExistsError(inst):
return getattr(inst, 'errno', _singleton) == errno.EEXIST
if platform.python_implementation() != "CPython":
try:
raise OSError(errno.EEXIST, "perm")
except FileExistsError:
pass
except OSError:
raise RuntimeError(
"broken / incompatible Python implementation, see: "
"https://github.com/giampaolo/psutil/issues/1659")
# --- stdlib additions

67
third_party/python/psutil/psutil/_psaix.py поставляемый
Просмотреть файл

@ -6,7 +6,6 @@
"""AIX platform implementation."""
import errno
import functools
import glob
import os
@ -14,21 +13,24 @@ import re
import subprocess
import sys
from collections import namedtuple
from socket import AF_INET
from . import _common
from . import _psposix
from . import _psutil_aix as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_to_ntuple
from ._common import get_procfs_path
from ._common import memoize_when_activated
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import NoSuchProcess
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
@ -80,13 +82,6 @@ proc_info_map = dict(
status=6,
ttynr=7)
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- named tuples
@ -220,27 +215,17 @@ def net_connections(kind, _pid=-1):
% (kind, ', '.join([repr(x) for x in cmap])))
families, types = _common.conn_tmap[kind]
rawlist = cext.net_connections(_pid)
ret = set()
ret = []
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
if fam not in families:
continue
if type_ not in types:
continue
status = TCP_STATUSES[status]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type_ = socktype_to_enum(type_)
if _pid == -1:
nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid)
else:
nt = _common.pconn(fd, fam, type_, laddr, raddr, status)
ret.add(nt)
return list(ret)
nt = conn_to_ntuple(fd, fam, type_, laddr, raddr, status,
TCP_STATUSES, pid=pid if _pid == -1 else None)
ret.append(nt)
return ret
def net_if_stats():
@ -327,22 +312,16 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
# support for private module import
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
except (FileNotFoundError, ProcessLookupError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
return wrapper
@ -501,11 +480,9 @@ class Process(object):
try:
result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid))
return result.rstrip('/')
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
raise
except FileNotFoundError:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
@wrap_exceptions
def memory_info(self):

127
third_party/python/psutil/psutil/_psbsd.py поставляемый
Просмотреть файл

@ -10,25 +10,29 @@ import functools
import os
import xml.etree.ElementTree as ET
from collections import namedtuple
from socket import AF_INET
from collections import defaultdict
from . import _common
from . import _psposix
from . import _psutil_bsd as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import FREEBSD
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NETBSD
from ._common import NoSuchProcess
from ._common import OPENBSD
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import which
__extra__all__ = []
@ -134,13 +138,6 @@ kinfo_proc_map = dict(
name=24,
)
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- named tuples
@ -399,22 +396,8 @@ def net_connections(kind):
fd, fam, type, laddr, raddr, status, pid = item
# TODO: apply filter at C level
if fam in families and type in types:
try:
status = TCP_STATUSES[status]
except KeyError:
# XXX: Not sure why this happens. I saw this occurring
# with IPv6 sockets opened by 'vim'. Those sockets
# have a very short lifetime so maybe the kernel
# can't initialize their status?
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES, pid)
ret.add(nt)
return list(ret)
@ -551,6 +534,14 @@ else:
pid_exists = _psposix.pid_exists
def is_zombie(pid):
try:
st = cext.proc_oneshot_info(pid)[kinfo_proc_map['status']]
return st == cext.SZOMB
except Exception:
return False
def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
@ -559,19 +550,19 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError as err:
except ProcessLookupError:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except OSError:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
if err.errno == errno.ESRCH:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
return wrapper
@ -581,18 +572,16 @@ def wrap_exceptions_procfs(inst):
"""Same as above, for routines relying on reading /proc fs."""
try:
yield
except EnvironmentError as err:
except (ProcessLookupError, FileNotFoundError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(inst.pid):
raise NoSuchProcess(inst.pid, inst._name)
else:
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(inst.pid, inst._name)
raise
if not pid_exists(inst.pid):
raise NoSuchProcess(inst.pid, inst._name)
else:
raise ZombieProcess(inst.pid, inst._name, inst._ppid)
except PermissionError:
raise AccessDenied(inst.pid, inst._name)
class Process(object):
@ -633,6 +622,8 @@ class Process(object):
@wrap_exceptions
def exe(self):
if FREEBSD:
if self.pid == 0:
return '' # else NSP
return cext.proc_exe(self.pid)
elif NETBSD:
if self.pid == 0:
@ -648,7 +639,7 @@ class Process(object):
# cmdline arg (may return None).
cmdline = self.cmdline()
if cmdline:
return which(cmdline[0])
return which(cmdline[0]) or ""
else:
return ""
@ -665,10 +656,14 @@ class Process(object):
return cext.proc_cmdline(self.pid)
except OSError as err:
if err.errno == errno.EINVAL:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
if is_zombie(self.pid):
raise ZombieProcess(self.pid, self._name, self._ppid)
elif not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name, self._ppid)
else:
# XXX: this happens with unicode tests. It means the C
# routine is unable to decode invalid unicode chars.
return []
else:
raise
else:
@ -769,25 +764,15 @@ class Process(object):
if NETBSD:
families, types = conn_tmap[kind]
ret = set()
ret = []
rawlist = cext.net_connections(self.pid)
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
assert pid == self.pid
if fam in families and type in types:
try:
status = TCP_STATUSES[status]
except KeyError:
status = TCP_STATUSES[cext.PSUTIL_CONN_NONE]
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.add(nt)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
self._assert_alive()
return list(ret)
@ -796,18 +781,13 @@ class Process(object):
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
status = TCP_STATUSES[status]
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
if OPENBSD:
self._assert_alive()
return ret
@wrap_exceptions
@ -844,10 +824,7 @@ class Process(object):
# it into None
if OPENBSD and self.pid == 0:
return None # ...else it would raise EINVAL
elif NETBSD:
with wrap_exceptions_procfs(self):
return os.readlink("/proc/%s/cwd" % self.pid)
elif HAS_PROC_OPEN_FILES:
elif NETBSD or HAS_PROC_OPEN_FILES:
# FreeBSD < 8 does not support functions based on
# kinfo_getfile() and kinfo_getvmmap()
return cext.proc_cwd(self.pid) or None

236
third_party/python/psutil/psutil/_pslinux.py поставляемый
Просмотреть файл

@ -25,6 +25,8 @@ from . import _common
from . import _psposix
from . import _psutil_linux as cext
from . import _psutil_posix as cext_posix
from ._common import AccessDenied
from ._common import debug
from ._common import decode
from ._common import get_procfs_path
from ._common import isfile_strict
@ -33,14 +35,19 @@ from ._common import memoize_when_activated
from ._common import NIC_DUPLEX_FULL
from ._common import NIC_DUPLEX_HALF
from ._common import NIC_DUPLEX_UNKNOWN
from ._common import NoSuchProcess
from ._common import open_binary
from ._common import open_text
from ._common import parse_environ_block
from ._common import path_exists_strict
from ._common import supports_ipv6
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import b
from ._compat import basestring
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
if sys.version_info >= (3, 4):
@ -70,6 +77,7 @@ POWER_SUPPLY_PATH = "/sys/class/power_supply"
HAS_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid())
HAS_PRLIMIT = hasattr(cext, "linux_prlimit")
HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get")
HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get")
_DEFAULT = object()
# RLIMIT_* constants, not guaranteed to be present on all kernels
@ -157,13 +165,6 @@ TCP_STATUSES = {
"0B": _common.CONN_CLOSING
}
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- named tuples
@ -200,6 +201,10 @@ pmmap_ext = namedtuple(
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_chars', 'write_chars'])
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes',
['user', 'system', 'children_user', 'children_system',
'iowait'])
# =====================================================================
@ -747,6 +752,8 @@ class Connections:
"""
def __init__(self):
# The string represents the basename of the corresponding
# /proc/net/{proto_name} file.
tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM)
tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM)
udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM)
@ -772,17 +779,16 @@ class Connections:
for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)):
try:
inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd))
except OSError as err:
except (FileNotFoundError, ProcessLookupError):
# ENOENT == file which is gone in the meantime;
# os.stat('/proc/%s' % self.pid) will be done later
# to force NSP (if it's the case)
if err.errno in (errno.ENOENT, errno.ESRCH):
continue
elif err.errno == errno.EINVAL:
continue
except OSError as err:
if err.errno == errno.EINVAL:
# not a link
continue
else:
raise
raise
else:
if inode.startswith('socket:['):
# the process is using a socket
@ -795,7 +801,7 @@ class Connections:
for pid in pids():
try:
inodes.update(self.get_proc_inodes(pid))
except OSError as err:
except (FileNotFoundError, ProcessLookupError, PermissionError):
# os.listdir() is gonna raise a lot of access denied
# exceptions in case of unprivileged user; that's fine
# as we'll just end up returning a connection with PID
@ -803,9 +809,7 @@ class Connections:
# Both netstat -an and lsof does the same so it's
# unlikely we can do any better.
# ENOENT just means a PID disappeared on us.
if err.errno not in (
errno.ENOENT, errno.ESRCH, errno.EPERM, errno.EACCES):
raise
continue
return inodes
@staticmethod
@ -933,7 +937,7 @@ class Connections:
path = tokens[-1]
else:
path = ""
type_ = int(type_)
type_ = _common.socktype_to_enum(int(type_))
# XXX: determining the remote endpoint of a
# UNIX socket on Linux is not possible, see:
# https://serverfault.com/questions/252723/
@ -954,15 +958,14 @@ class Connections:
else:
inodes = self.get_all_inodes()
ret = set()
for f, family, type_ in self.tmap[kind]:
for proto_name, family, type_ in self.tmap[kind]:
path = "%s/net/%s" % (self._procfs_path, proto_name)
if family in (socket.AF_INET, socket.AF_INET6):
ls = self.process_inet(
"%s/net/%s" % (self._procfs_path, f),
family, type_, inodes, filter_pid=pid)
path, family, type_, inodes, filter_pid=pid)
else:
ls = self.process_unix(
"%s/net/%s" % (self._procfs_path, f),
family, inodes, filter_pid=pid)
path, family, inodes, filter_pid=pid)
for fd, family, type_, laddr, raddr, status, bound_pid in ls:
if pid:
conn = _common.pconn(fd, family, type_, laddr, raddr,
@ -1065,6 +1068,7 @@ def disk_io_counters(perdisk=False):
# "3 1 hda1 8 8 8 8"
# 4.18+ has 4 fields added:
# "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0"
# 5.5 has 2 more fields.
# See:
# https://www.kernel.org/doc/Documentation/iostats.txt
# https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
@ -1079,7 +1083,7 @@ def disk_io_counters(perdisk=False):
reads = int(fields[2])
(reads_merged, rbytes, rtime, writes, writes_merged,
wbytes, wtime, _, busy_time, _) = map(int, fields[4:14])
elif flen == 14 or flen == 18:
elif flen == 14 or flen >= 18:
# Linux 2.6+, line referring to a disk
name = fields[2]
(reads, reads_merged, rbytes, rtime, writes, writes_merged,
@ -1103,7 +1107,7 @@ def disk_io_counters(perdisk=False):
fields = f.read().strip().split()
name = os.path.basename(root)
(reads, reads_merged, rbytes, rtime, writes, writes_merged,
wbytes, wtime, _, busy_time, _) = map(int, fields)
wbytes, wtime, _, busy_time) = map(int, fields[:10])
yield (name, reads, writes, rbytes, wbytes, rtime,
wtime, reads_merged, writes_merged, busy_time)
@ -1174,6 +1178,7 @@ def disk_partitions(all=False):
continue
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
@ -1201,6 +1206,8 @@ def sensors_temperatures():
# https://github.com/giampaolo/psutil/issues/971
# https://github.com/nicolargo/glances/issues/1060
basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*'))
basenames.extend(glob.glob(
'/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*'))
basenames = sorted(set([x.split('_')[0] for x in basenames]))
for base in basenames:
@ -1209,7 +1216,7 @@ def sensors_temperatures():
current = float(cat(path)) / 1000.0
path = os.path.join(os.path.dirname(base), 'name')
unit_name = cat(path, binary=False)
except (IOError, OSError, ValueError) as err:
except (IOError, OSError, ValueError):
# A lot of things can go wrong here, so let's just skip the
# whole entry. Sure thing is Linux's /sys/class/hwmon really
# is a stinky broken mess.
@ -1218,8 +1225,6 @@ def sensors_temperatures():
# https://github.com/giampaolo/psutil/issues/1129
# https://github.com/giampaolo/psutil/issues/1245
# https://github.com/giampaolo/psutil/issues/1323
warnings.warn("ignoring %r for file %r" % (err, path),
RuntimeWarning)
continue
high = cat(base + '_max', fallback=None)
@ -1251,8 +1256,7 @@ def sensors_temperatures():
path = os.path.join(base, 'type')
unit_name = cat(path, binary=False)
except (IOError, OSError, ValueError) as err:
warnings.warn("ignoring %r for file %r" % (err, path),
RuntimeWarning)
debug("ignoring %r for file %r" % (err, path))
continue
trip_paths = glob.glob(base + '/trip_point*')
@ -1490,11 +1494,10 @@ def ppid_map():
try:
with open_binary("%s/%s/stat" % (procfs_path, pid)) as f:
data = f.read()
except EnvironmentError as err:
except (FileNotFoundError, ProcessLookupError):
# Note: we should be able to access /stat for all processes
# aka it's unlikely we'll bump into EPERM, which is good.
if err.errno not in (errno.ENOENT, errno.ESRCH):
raise
pass
else:
rpar = data.rfind(b')')
dset = data[rpar + 2:].split()
@ -1511,16 +1514,12 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
# ESRCH (no such process) can be raised on read() if
# process is gone in the meantime.
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
# ENOENT (no such file or directory) can be raised on open().
if err.errno == errno.ENOENT and not os.path.exists("%s/%s" % (
self._procfs_path, self.pid)):
except PermissionError:
raise AccessDenied(self.pid, self._name)
except ProcessLookupError:
raise NoSuchProcess(self.pid, self._name)
except FileNotFoundError:
if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)):
raise NoSuchProcess(self.pid, self._name)
# Note: zombies will keep existing under /proc until they're
# gone so there's no way to distinguish them in here.
@ -1576,6 +1575,7 @@ class Process(object):
ret['children_stime'] = fields[14]
ret['create_time'] = fields[19]
ret['cpu_num'] = fields[36]
ret['blkio_ticks'] = fields[39] # aka 'delayacct_blkio_ticks'
return ret
@ -1617,21 +1617,19 @@ class Process(object):
def exe(self):
try:
return readlink("%s/%s/exe" % (self._procfs_path, self.pid))
except OSError as err:
if err.errno in (errno.ENOENT, errno.ESRCH):
# no such file error; might be raised also if the
# path actually exists for system processes with
# low pids (about 0-20)
if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
return ""
except (FileNotFoundError, ProcessLookupError):
# no such file error; might be raised also if the
# path actually exists for system processes with
# low pids (about 0-20)
if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)):
return ""
else:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
@wrap_exceptions
def cmdline(self):
@ -1650,7 +1648,13 @@ class Process(object):
sep = '\x00' if data.endswith('\x00') else ' '
if data.endswith(sep):
data = data[:-1]
return data.split(sep)
cmdline = data.split(sep)
# Sometimes last char is a null byte '\0' but the args are
# separated by spaces, see: https://github.com/giampaolo/psutil/
# issues/1179#issuecomment-552984549
if sep == '\x00' and len(cmdline) == 1 and ' ' in data:
cmdline = data.split(' ')
return cmdline
@wrap_exceptions
def environ(self):
@ -1707,7 +1711,8 @@ class Process(object):
stime = float(values['stime']) / CLOCK_TICKS
children_utime = float(values['children_utime']) / CLOCK_TICKS
children_stime = float(values['children_stime']) / CLOCK_TICKS
return _common.pcputimes(utime, stime, children_utime, children_stime)
iowait = float(values['blkio_ticks']) / CLOCK_TICKS
return pcputimes(utime, stime, children_utime, children_stime, iowait)
@wrap_exceptions
def cpu_num(self):
@ -1839,7 +1844,7 @@ class Process(object):
path = path[:-10]
ls.append((
decode(addr), decode(perms), path,
data[b'Rss:'],
data.get(b'Rss:', 0),
data.get(b'Size:', 0),
data.get(b'Pss:', 0),
data.get(b'Shared_Clean:', 0),
@ -1856,14 +1861,12 @@ class Process(object):
def cwd(self):
try:
return readlink("%s/%s/cwd" % (self._procfs_path, self.pid))
except OSError as err:
except (FileNotFoundError, ProcessLookupError):
# https://github.com/giampaolo/psutil/issues/986
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
raise
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
@wrap_exceptions
def num_ctx_switches(self,
@ -1899,13 +1902,11 @@ class Process(object):
try:
with open_binary(fname) as f:
st = f.read().strip()
except IOError as err:
if err.errno == errno.ENOENT:
# no such file or directory; it means thread
# disappeared on us
hit_enoent = True
continue
raise
except FileNotFoundError:
# no such file or directory; it means thread
# disappeared on us
hit_enoent = True
continue
# ignore the first two values ("pid (exe)")
st = st[st.find(b')') + 2:]
values = st.split(b' ')
@ -1930,38 +1931,41 @@ class Process(object):
def nice_set(self, value):
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def cpu_affinity_get(self):
return cext.proc_cpu_affinity_get(self.pid)
# starting from CentOS 6.
if HAS_CPU_AFFINITY:
def _get_eligible_cpus(
self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")):
# See: https://github.com/giampaolo/psutil/issues/956
data = self._read_status_file()
match = _re.findall(data)
if match:
return list(range(int(match[0][0]), int(match[0][1]) + 1))
else:
return list(range(len(per_cpu_times())))
@wrap_exceptions
def cpu_affinity_get(self):
return cext.proc_cpu_affinity_get(self.pid)
@wrap_exceptions
def cpu_affinity_set(self, cpus):
try:
cext.proc_cpu_affinity_set(self.pid, cpus)
except (OSError, ValueError) as err:
if isinstance(err, ValueError) or err.errno == errno.EINVAL:
eligible_cpus = self._get_eligible_cpus()
all_cpus = tuple(range(len(per_cpu_times())))
for cpu in cpus:
if cpu not in all_cpus:
raise ValueError(
"invalid CPU number %r; choose between %s" % (
cpu, eligible_cpus))
if cpu not in eligible_cpus:
raise ValueError(
"CPU number %r is not eligible; choose "
"between %s" % (cpu, eligible_cpus))
raise
def _get_eligible_cpus(
self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")):
# See: https://github.com/giampaolo/psutil/issues/956
data = self._read_status_file()
match = _re.findall(data)
if match:
return list(range(int(match[0][0]), int(match[0][1]) + 1))
else:
return list(range(len(per_cpu_times())))
@wrap_exceptions
def cpu_affinity_set(self, cpus):
try:
cext.proc_cpu_affinity_set(self.pid, cpus)
except (OSError, ValueError) as err:
if isinstance(err, ValueError) or err.errno == errno.EINVAL:
eligible_cpus = self._get_eligible_cpus()
all_cpus = tuple(range(len(per_cpu_times())))
for cpu in cpus:
if cpu not in all_cpus:
raise ValueError(
"invalid CPU number %r; choose between %s" % (
cpu, eligible_cpus))
if cpu not in eligible_cpus:
raise ValueError(
"CPU number %r is not eligible; choose "
"between %s" % (cpu, eligible_cpus))
raise
# only starting from kernel 2.6.13
if HAS_PROC_IO_PRIORITY:
@ -2029,16 +2033,15 @@ class Process(object):
file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd)
try:
path = readlink(file)
except OSError as err:
except (FileNotFoundError, ProcessLookupError):
# ENOENT == file which is gone in the meantime
if err.errno in (errno.ENOENT, errno.ESRCH):
hit_enoent = True
continue
elif err.errno == errno.EINVAL:
hit_enoent = True
continue
except OSError as err:
if err.errno == errno.EINVAL:
# not a link
continue
else:
raise
raise
else:
# If path is not an absolute there's no way to tell
# whether it's a regular file or not, so we skip it.
@ -2052,13 +2055,10 @@ class Process(object):
with open_binary(file) as f:
pos = int(f.readline().split()[1])
flags = int(f.readline().split()[1], 8)
except IOError as err:
if err.errno == errno.ENOENT:
# fd gone in the meantime; process may
# still be alive
hit_enoent = True
else:
raise
except FileNotFoundError:
# fd gone in the meantime; process may
# still be alive
hit_enoent = True
else:
mode = file_flags_to_mode(flags)
ntuple = popenfile(

38
third_party/python/psutil/psutil/_psosx.py поставляемый
Просмотреть файл

@ -8,21 +8,23 @@ import contextlib
import errno
import functools
import os
from socket import AF_INET
from collections import namedtuple
from . import _common
from . import _psposix
from . import _psutil_osx as cext
from . import _psutil_posix as cext_posix
from ._common import AF_INET6
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import PermissionError
from ._compat import ProcessLookupError
__extra__all__ = []
@ -84,13 +86,6 @@ pidtaskinfo_map = dict(
volctxsw=7,
)
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- named tuples
@ -337,12 +332,10 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError as err:
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
except ProcessLookupError:
raise NoSuchProcess(self.pid, self._name)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except cext.ZombieProcessError:
raise ZombieProcess(self.pid, self._name, self._ppid)
return wrapper
@ -529,15 +522,8 @@ class Process(object):
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status,
TCP_STATUSES)
ret.append(nt)
return ret

69
third_party/python/psutil/psutil/_psposix.py поставляемый
Просмотреть файл

@ -4,7 +4,6 @@
"""Routines common to all posix systems."""
import errno
import glob
import os
import sys
@ -12,7 +11,13 @@ import time
from ._common import memoize
from ._common import sdiskusage
from ._common import TimeoutExpired
from ._common import usage_percent
from ._compat import ChildProcessError
from ._compat import FileNotFoundError
from ._compat import InterruptedError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
from ._compat import unicode
@ -20,11 +25,6 @@ from ._compat import unicode
__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
# This object gets set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
TimeoutExpired = None
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if pid == 0:
@ -36,19 +36,13 @@ def pid_exists(pid):
return True
try:
os.kill(pid, 0)
except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
elif err.errno == errno.EPERM:
# EPERM clearly means there's a process to deny access to
return True
else:
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH) therefore we should never get
# here. If we do let's be explicit in considering this
# an error.
raise err
except ProcessLookupError:
return False
except PermissionError:
# EPERM clearly means there's a process to deny access to
return True
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH)
else:
return True
@ -84,24 +78,20 @@ def wait_pid(pid, timeout=None, proc_name=None):
while True:
try:
retpid, status = waitcall()
except OSError as err:
if err.errno == errno.EINTR:
delay = check_timeout(delay)
continue
elif err.errno == errno.ECHILD:
# This has two meanings:
# - pid is not a child of os.getpid() in which case
# we keep polling until it's gone
# - pid never existed in the first place
# In both cases we'll eventually return None as we
# can't determine its exit status code.
while True:
if pid_exists(pid):
delay = check_timeout(delay)
else:
return
else:
raise
except InterruptedError:
delay = check_timeout(delay)
except ChildProcessError:
# This has two meanings:
# - pid is not a child of os.getpid() in which case
# we keep polling until it's gone
# - pid never existed in the first place
# In both cases we'll eventually return None as we
# can't determine its exit status code.
while True:
if pid_exists(pid):
delay = check_timeout(delay)
else:
return
else:
if retpid == 0:
# WNOHANG was used, pid is still running
@ -180,7 +170,6 @@ def get_terminal_map():
assert name not in ret, name
try:
ret[os.stat(name).st_rdev] = name
except OSError as err:
if err.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
return ret

72
third_party/python/psutil/psutil/_pssunos.py поставляемый
Просмотреть файл

@ -17,14 +17,21 @@ from . import _common
from . import _psposix
from . import _psutil_posix as cext_posix
from . import _psutil_sunos as cext
from ._common import AccessDenied
from ._common import AF_INET6
from ._common import debug
from ._common import get_procfs_path
from ._common import isfile_strict
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import usage_percent
from ._common import ZombieProcess
from ._compat import b
from ._compat import FileNotFoundError
from ._compat import PermissionError
from ._compat import ProcessLookupError
from ._compat import PY3
@ -84,13 +91,6 @@ proc_info_map = dict(
gid=10,
egid=11)
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# =====================================================================
# --- named tuples
@ -226,7 +226,12 @@ def disk_partitions(all=False):
# Differently from, say, Linux, we don't have a list of
# common fs types so the best we can do, AFAIK, is to
# filter by filesystem having a total size > 0.
if not disk_usage(mountpoint).total:
try:
if not disk_usage(mountpoint).total:
continue
except OSError as err:
# https://github.com/giampaolo/psutil/issues/1674
debug("skipping %r: %r" % (mountpoint, err))
continue
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
@ -262,6 +267,7 @@ def net_connections(kind, _pid=-1):
continue
if type_ not in types:
continue
# TODO: refactor and use _common.conn_to_ntuple.
if fam in (AF_INET, AF_INET6):
if laddr:
laddr = _common.addr(*laddr)
@ -341,22 +347,22 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError as err:
except (FileNotFoundError, ProcessLookupError):
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
except PermissionError:
raise AccessDenied(self.pid, self._name)
except OSError:
if self.pid == 0:
if 0 in pids():
raise AccessDenied(self.pid, self._name)
else:
raise
# ENOENT (no such file or directory) gets raised on open().
# ESRCH (no such process) can get raised on read() if
# process is gone in meantime.
if err.errno in (errno.ENOENT, errno.ESRCH):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._name)
else:
raise ZombieProcess(self.pid, self._name, self._ppid)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._name)
raise
return wrapper
@ -396,6 +402,9 @@ class Process(object):
@wrap_exceptions
@memoize_when_activated
def _proc_basic_info(self):
if self.pid == 0 and not \
os.path.exists('%s/%s/psinfo' % (self._procfs_path, self.pid)):
raise AccessDenied(self.pid)
ret = cext.proc_basic_info(self.pid, self._procfs_path)
assert len(ret) == len(proc_info_map)
return ret
@ -514,11 +523,9 @@ class Process(object):
try:
return os.readlink(
'%s/%d/path/%d' % (procfs_path, self.pid, x))
except OSError as err:
if err.errno == errno.ENOENT:
hit_enoent = True
continue
raise
except FileNotFoundError:
hit_enoent = True
continue
if hit_enoent:
self._assert_alive()
@ -531,11 +538,9 @@ class Process(object):
procfs_path = self._procfs_path
try:
return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid))
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
raise
except FileNotFoundError:
os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD
return None
@wrap_exceptions
def memory_info(self):
@ -596,12 +601,9 @@ class Process(object):
if os.path.islink(path):
try:
file = os.readlink(path)
except OSError as err:
# ENOENT == file which is gone in the meantime
if err.errno == errno.ENOENT:
hit_enoent = True
continue
raise
except FileNotFoundError:
hit_enoent = True
continue
else:
if isfile_strict(file):
retlist.append(_common.popenfile(file, int(fd)))

Просмотреть файл

@ -15,7 +15,7 @@
* - psutil.Process.io_counters read count is always 0
* - psutil.Process.io_counters may not be available on older AIX versions
* - psutil.Process.threads may not be available on older AIX versions
# - psutil.net_io_counters may not be available on older AIX versions
* - psutil.net_io_counters may not be available on older AIX versions
* - reading basic process info may fail or return incorrect values when
* process is starting (see IBM APAR IV58499 - fixed in newer AIX versions)
* - sockets and pipes may not be counted in num_fds (fixed in newer AIX
@ -29,7 +29,6 @@
*/
#include <Python.h>
#include <sys/limits.h>
#include <sys/proc.h>
#include <sys/procfs.h>
@ -51,11 +50,11 @@
#include <libperfstat.h>
#include <unistd.h>
#include "_psutil_common.h"
#include "_psutil_posix.h"
#include "arch/aix/ifaddrs.h"
#include "arch/aix/net_connections.h"
#include "arch/aix/common.h"
#include "_psutil_common.h"
#include "_psutil_posix.h"
#define TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec)
@ -180,7 +179,7 @@ psutil_proc_args(PyObject *self, PyObject *args) {
}
procbuf.pi_pid = pid;
ret = getargs(&procbuf, sizeof(struct procinfo), argbuf, ARG_MAX);
ret = getargs(&procbuf, sizeof(procbuf), argbuf, ARG_MAX);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
@ -241,7 +240,7 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
}
procbuf.pi_pid = pid;
ret = getevars(&procbuf, sizeof(struct procinfo), envbuf, ARG_MAX);
ret = getevars(&procbuf, sizeof(procbuf), envbuf, ARG_MAX);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
@ -265,8 +264,8 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
goto error;
if (PyDict_SetItem(py_retdict, py_key, py_val))
goto error;
Py_DECREF(py_key);
Py_DECREF(py_val);
Py_CLEAR(py_key);
Py_CLEAR(py_val);
}
curvar = strchr(curvar, '\0') + 1;
}
@ -462,7 +461,7 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) {
/* finished iteration without finding requested pid */
free(processes);
return NoSuchProcess("");
return NoSuchProcess("psutil_read_process_table (no PID found)");
}
@ -510,10 +509,10 @@ psutil_users(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
}
endutxent();
@ -570,9 +569,9 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
Py_CLEAR(py_dev);
Py_CLEAR(py_mountp);
Py_CLEAR(py_tuple);
mt = getmntent(file);
}
endmntent(file);

278
third_party/python/psutil/psutil/_psutil_bsd.c поставляемый
Просмотреть файл

@ -31,7 +31,7 @@
#include <sys/param.h>
#include <sys/sysctl.h>
#if !defined(__NetBSD__)
#include <sys/user.h>
#include <sys/user.h>
#endif
#include <sys/proc.h>
#include <sys/file.h>
@ -51,13 +51,10 @@
#include <netinet/tcp_var.h> // for struct xtcpcb
#include <netinet/tcp_fsm.h> // for TCP connection states
#include <arpa/inet.h> // for inet_ntop()
#include <sys/mount.h>
#include <net/if.h> // net io counters
#include <net/if_dl.h>
#include <net/route.h>
#include <netinet/in.h> // process open files/connections
#include <sys/un.h>
@ -99,7 +96,6 @@
#endif
// convert a timeval struct to a double
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
@ -129,32 +125,22 @@ psutil_pids(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
// TODO: RuntimeError is inappropriate here; we could return the
// original error instead.
if (psutil_get_proc_list(&proclist, &num_processes) != 0) {
if (errno != 0) {
PyErr_SetFromErrno(PyExc_OSError);
}
else {
PyErr_SetString(PyExc_RuntimeError,
"failed to retrieve process list");
}
if (psutil_get_proc_list(&proclist, &num_processes) != 0)
goto error;
}
if (num_processes > 0) {
orig_address = proclist; // save so we can free it after we're done
for (idx = 0; idx < num_processes; idx++) {
#ifdef PSUTIL_FREEBSD
py_pid = Py_BuildValue("i", proclist->ki_pid);
py_pid = PyLong_FromPid(proclist->ki_pid);
#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
py_pid = Py_BuildValue("i", proclist->p_pid);
py_pid = PyLong_FromPid(proclist->p_pid);
#endif
if (!py_pid)
goto error;
if (PyList_Append(py_retlist, py_pid))
goto error;
Py_DECREF(py_pid);
Py_CLEAR(py_pid);
proclist++;
}
free(orig_address);
@ -194,7 +180,7 @@ psutil_boot_time(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
long rss;
long vms;
long memtext;
@ -205,9 +191,10 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
long pagesize = sysconf(_SC_PAGESIZE);
char str[1000];
PyObject *py_name;
PyObject *py_ppid;
PyObject *py_retlist;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -269,12 +256,25 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
oncpu = -1;
#endif
#ifdef PSUTIL_FREEBSD
py_ppid = PyLong_FromPid(kp.ki_ppid);
#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
py_ppid = PyLong_FromPid(kp.p_ppid);
#else
py_ppid = Py_BuildfValue(-1);
#endif
if (! py_ppid)
return NULL;
// Return a single big tuple with all process info.
py_retlist = Py_BuildValue(
"(lillllllidllllddddlllllbO)",
#if defined(__FreeBSD_version) && __FreeBSD_version >= 1200031
"(OillllllLdllllddddlllllbO)",
#else
"(OillllllidllllddddlllllbO)",
#endif
#ifdef PSUTIL_FREEBSD
//
(long)kp.ki_ppid, // (long) ppid
py_ppid, // (pid_t) ppid
(int)kp.ki_stat, // (int) status
// UIDs
(long)kp.ki_ruid, // (long) real uid
@ -285,7 +285,7 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
(long)kp.ki_groups[0], // (long) effective gid
(long)kp.ki_svuid, // (long) saved gid
//
kp.ki_tdev, // (int) tty nr
kp.ki_tdev, // (int or long long) tty nr
PSUTIL_TV2DOUBLE(kp.ki_start), // (double) create time
// ctx switches
kp.ki_rusage.ru_nvcsw, // (long) ctx switches (voluntary)
@ -307,8 +307,7 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
// others
oncpu, // (int) the CPU we are on
#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
//
(long)kp.p_ppid, // (long) ppid
py_ppid, // (pid_t) ppid
(int)kp.p_stat, // (int) status
// UIDs
(long)kp.p_ruid, // (long) real uid
@ -347,6 +346,7 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
);
Py_DECREF(py_name);
Py_DECREF(py_ppid);
return py_retlist;
}
@ -356,11 +356,11 @@ psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_name(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
kinfo_proc kp;
char str[1000];
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -379,10 +379,10 @@ psutil_proc_name(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_cmdline(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
PyObject *py_retlist = NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
py_retlist = psutil_get_cmdline(pid);
if (py_retlist == NULL)
@ -452,7 +452,7 @@ psutil_cpu_times(PyObject *self, PyObject *args) {
#if (defined(__FreeBSD_version) && __FreeBSD_version >= 800000) || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD)
static PyObject *
psutil_proc_open_files(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int i;
int cnt;
int regular;
@ -467,7 +467,7 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
if (psutil_kinfo_proc(pid, &kipp) == -1)
goto error;
@ -475,7 +475,9 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
#if !defined(PSUTIL_OPENBSD)
psutil_raise_for_pid(pid, "kinfo_getfile()");
#endif
goto error;
}
@ -507,8 +509,8 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_path);
Py_DECREF(py_tuple);
Py_CLEAR(py_path);
Py_CLEAR(py_tuple);
}
}
free(freep);
@ -670,9 +672,9 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
Py_CLEAR(py_dev);
Py_CLEAR(py_mountp);
Py_CLEAR(py_tuple);
}
free(fs);
@ -765,7 +767,7 @@ psutil_net_io_counters(PyObject *self, PyObject *args) {
goto error;
if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
Py_CLEAR(py_ifc_info);
}
else {
continue;
@ -794,6 +796,7 @@ psutil_users(PyObject *self, PyObject *args) {
PyObject *py_tty = NULL;
PyObject *py_hostname = NULL;
PyObject *py_tuple = NULL;
PyObject *py_pid = NULL;
if (py_retlist == NULL)
return NULL;
@ -802,7 +805,9 @@ psutil_users(PyObject *self, PyObject *args) {
struct utmp ut;
FILE *fp;
Py_BEGIN_ALLOW_THREADS
fp = fopen(_PATH_UTMP, "r");
Py_END_ALLOW_THREADS
if (fp == NULL) {
PyErr_SetFromErrnoWithFilename(PyExc_OSError, _PATH_UTMP);
goto error;
@ -829,7 +834,7 @@ psutil_users(PyObject *self, PyObject *args) {
#ifdef PSUTIL_OPENBSD
-1 // process id (set to None later)
#else
ut.ut_pid // process id
ut.ut_pid // TODO: use PyLong_FromPid
#endif
);
if (!py_tuple) {
@ -840,10 +845,10 @@ psutil_users(PyObject *self, PyObject *args) {
fclose(fp);
goto error;
}
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
}
fclose(fp);
@ -862,17 +867,21 @@ psutil_users(PyObject *self, PyObject *args) {
py_hostname = PyUnicode_DecodeFSDefault(utx->ut_host);
if (! py_hostname)
goto error;
#ifdef PSUTIL_OPENBSD
py_pid = Py_BuildValue("i", -1); // set to None later
#else
py_pid = PyLong_FromPid(utx->ut_pid);
#endif
if (! py_pid)
goto error;
py_tuple = Py_BuildValue(
"(OOOfi)",
"(OOOfO)",
py_username, // username
py_tty, // tty
py_hostname, // hostname
(float)utx->ut_tv.tv_sec, // start time
#ifdef PSUTIL_OPENBSD
-1 // process id (set to None later)
#else
utx->ut_pid // process id
#endif
py_pid // process id
);
if (!py_tuple) {
@ -883,10 +892,11 @@ psutil_users(PyObject *self, PyObject *args) {
endutxent();
goto error;
}
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
Py_CLEAR(py_pid);
}
endutxent();
@ -898,6 +908,7 @@ error:
Py_XDECREF(py_tty);
Py_XDECREF(py_hostname);
Py_XDECREF(py_tuple);
Py_XDECREF(py_pid);
Py_DECREF(py_retlist);
return NULL;
}
@ -906,8 +917,7 @@ error:
/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] = {
static PyMethodDef mod_methods[] = {
// --- per-process functions
{"proc_oneshot_info", psutil_proc_oneshot_info, METH_VARARGS,
@ -921,9 +931,9 @@ PsutilMethods[] = {
#if defined(PSUTIL_FREEBSD) || defined(PSUTIL_OPENBSD)
{"proc_connections", psutil_proc_connections, METH_VARARGS,
"Return connections opened by process"},
#endif
{"proc_cwd", psutil_proc_cwd, METH_VARARGS,
"Return process current working directory."},
#endif
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 || PSUTIL_OPENBSD || defined(PSUTIL_NETBSD)
{"proc_num_fds", psutil_proc_num_fds, METH_VARARGS,
"Return the number of file descriptors opened by this process"},
@ -994,109 +1004,99 @@ PsutilMethods[] = {
{NULL, NULL, 0, NULL}
};
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
#endif
#define INITERR return NULL
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_psutil_bsd",
NULL,
-1,
mod_methods,
NULL,
NULL,
NULL,
NULL
};
static int
psutil_bsd_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
PyObject *PyInit__psutil_bsd(void)
#else /* PY_MAJOR_VERSION */
#define INITERR return
static int
psutil_bsd_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef
moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_bsd",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_bsd_traverse,
psutil_bsd_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__psutil_bsd(void)
#else
#define INITERROR return
void init_psutil_bsd(void)
#endif
void init_psutil_bsd(void)
#endif /* PY_MAJOR_VERSION */
{
PyObject *v;
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *mod = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_bsd", PsutilMethods);
PyObject *mod = Py_InitModule("_psutil_bsd", mod_methods);
#endif
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
if (mod == NULL)
INITERR;
if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR;
// process status constants
#ifdef PSUTIL_FREEBSD
PyModule_AddIntConstant(module, "SIDL", SIDL);
PyModule_AddIntConstant(module, "SRUN", SRUN);
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
PyModule_AddIntConstant(module, "SZOMB", SZOMB);
PyModule_AddIntConstant(module, "SWAIT", SWAIT);
PyModule_AddIntConstant(module, "SLOCK", SLOCK);
if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR;
if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR;
if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR;
if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR;
if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR;
if (PyModule_AddIntConstant(mod, "SWAIT", SWAIT)) INITERR;
if (PyModule_AddIntConstant(mod, "SLOCK", SLOCK)) INITERR;
#elif PSUTIL_OPENBSD
PyModule_AddIntConstant(module, "SIDL", SIDL);
PyModule_AddIntConstant(module, "SRUN", SRUN);
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
PyModule_AddIntConstant(module, "SZOMB", SZOMB); // unused
PyModule_AddIntConstant(module, "SDEAD", SDEAD);
PyModule_AddIntConstant(module, "SONPROC", SONPROC);
if (PyModule_AddIntConstant(mod, "SIDL", SIDL)) INITERR;
if (PyModule_AddIntConstant(mod, "SRUN", SRUN)) INITERR;
if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP)) INITERR;
if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP)) INITERR;
if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB)) INITERR; // unused
if (PyModule_AddIntConstant(mod, "SDEAD", SDEAD)) INITERR;
if (PyModule_AddIntConstant(mod, "SONPROC", SONPROC)) INITERR;
#elif defined(PSUTIL_NETBSD)
PyModule_AddIntConstant(module, "SIDL", LSIDL);
PyModule_AddIntConstant(module, "SRUN", LSRUN);
PyModule_AddIntConstant(module, "SSLEEP", LSSLEEP);
PyModule_AddIntConstant(module, "SSTOP", LSSTOP);
PyModule_AddIntConstant(module, "SZOMB", LSZOMB);
PyModule_AddIntConstant(module, "SDEAD", LSDEAD);
PyModule_AddIntConstant(module, "SONPROC", LSONPROC);
if (PyModule_AddIntConstant(mod, "SIDL", LSIDL)) INITERR;
if (PyModule_AddIntConstant(mod, "SRUN", LSRUN)) INITERR;
if (PyModule_AddIntConstant(mod, "SSLEEP", LSSLEEP)) INITERR;
if (PyModule_AddIntConstant(mod, "SSTOP", LSSTOP)) INITERR;
if (PyModule_AddIntConstant(mod, "SZOMB", LSZOMB)) INITERR;
if (PyModule_AddIntConstant(mod, "SDEAD", LSDEAD)) INITERR;
if (PyModule_AddIntConstant(mod, "SONPROC", LSONPROC)) INITERR;
// unique to NetBSD
PyModule_AddIntConstant(module, "SSUSPENDED", LSSUSPENDED);
if (PyModule_AddIntConstant(mod, "SSUSPENDED", LSSUSPENDED)) INITERR;
#endif
// connection status constants
PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED);
PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING);
PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT);
PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN);
PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED);
PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT);
PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED);
PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1);
PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2);
PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK);
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT))
INITERR;
// PSUTIL_CONN_NONE
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", 128);
if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", 128)) INITERR;
psutil_setup();
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
#if PY_MAJOR_VERSION >= 3
return module;
return mod;
#endif
}

Просмотреть файл

@ -7,52 +7,64 @@
*/
#include <Python.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "_psutil_common.h"
// Global vars.
// ====================================================================
// --- Global vars
// ====================================================================
int PSUTIL_DEBUG = 0;
int PSUTIL_TESTING = 0;
// PSUTIL_CONN_NONE
/*
* Backport of unicode FS APIs from Python 3.
* On Python 2 we just return a plain byte string
* which is never supposed to raise decoding errors.
* See: https://github.com/giampaolo/psutil/issues/1040
*/
#if PY_MAJOR_VERSION < 3
// ====================================================================
// --- Backward compatibility with missing Python.h APIs
// ====================================================================
// PyPy on Windows
#if defined(PSUTIL_WINDOWS) && \
defined(PYPY_VERSION) && \
!defined(PyErr_SetFromWindowsErrWithFilename)
PyObject *
PyUnicode_DecodeFSDefault(char *s) {
return PyString_FromString(s);
}
PyErr_SetFromWindowsErrWithFilename(int winerr, const char *filename) {
PyObject *py_exc = NULL;
PyObject *py_winerr = NULL;
if (winerr == 0)
winerr = GetLastError();
if (filename == NULL) {
py_exc = PyObject_CallFunction(PyExc_OSError, "(is)", winerr,
strerror(winerr));
}
else {
py_exc = PyObject_CallFunction(PyExc_OSError, "(iss)", winerr,
strerror(winerr), filename);
}
if (py_exc == NULL)
return NULL;
PyObject *
PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size) {
return PyString_FromStringAndSize(s, size);
}
#endif
py_winerr = Py_BuildValue("i", winerr);
if (py_winerr == NULL)
goto error;
if (PyObject_SetAttrString(py_exc, "winerror", py_winerr) != 0)
goto error;
PyErr_SetObject(PyExc_OSError, py_exc);
Py_XDECREF(py_exc);
return NULL;
/*
* Set OSError(errno=ESRCH, strerror="No such process") Python exception.
* If msg != "" the exception message will change in accordance.
*/
PyObject *
NoSuchProcess(const char *msg) {
PyObject *exc;
exc = PyObject_CallFunction(
PyExc_OSError, "(is)", ESRCH, strlen(msg) ? msg : strerror(ESRCH));
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
error:
Py_XDECREF(py_exc);
Py_XDECREF(py_winerr);
return NULL;
}
#endif // PYPY on Windows
// ====================================================================
// --- Custom exceptions
// ====================================================================
/*
* Same as PyErr_SetFromErrno(0) but adds the syscall to the exception
* message.
@ -61,7 +73,7 @@ PyObject *
PyErr_SetFromOSErrnoWithSyscall(const char *syscall) {
char fullmsg[1024];
#ifdef _WIN32
#ifdef PSUTIL_WINDOWS
sprintf(fullmsg, "(originated from %s)", syscall);
PyErr_SetFromWindowsErrWithFilename(GetLastError(), fullmsg);
#else
@ -76,20 +88,43 @@ PyErr_SetFromOSErrnoWithSyscall(const char *syscall) {
/*
* Set OSError(errno=EACCES, strerror="Permission denied") Python exception.
* If msg != "" the exception message will change in accordance.
* Set OSError(errno=ESRCH, strerror="No such process (originated from")
* Python exception.
*/
PyObject *
AccessDenied(const char *msg) {
NoSuchProcess(const char *syscall) {
PyObject *exc;
exc = PyObject_CallFunction(
PyExc_OSError, "(is)", EACCES, strlen(msg) ? msg : strerror(EACCES));
char msg[1024];
sprintf(msg, "No such process (originated from %s)", syscall);
exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg);
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
return NULL;
}
/*
* Set OSError(errno=EACCES, strerror="Permission denied" (originated from ...)
* Python exception.
*/
PyObject *
AccessDenied(const char *syscall) {
PyObject *exc;
char msg[1024];
sprintf(msg, "Access denied (originated from %s)", syscall);
exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg);
PyErr_SetObject(PyExc_OSError, exc);
Py_XDECREF(exc);
return NULL;
}
// ====================================================================
// --- Global utils
// ====================================================================
/*
* Enable testing mode. This has the same effect as setting PSUTIL_TESTING
* env var. This dual method exists because updating os.environ on
@ -130,3 +165,239 @@ psutil_setup(void) {
PSUTIL_TESTING = 1;
return 0;
}
// ====================================================================
// --- Windows
// ====================================================================
#ifdef PSUTIL_WINDOWS
#include <windows.h>
// Needed to make these globally visible.
int PSUTIL_WINVER;
SYSTEM_INFO PSUTIL_SYSTEM_INFO;
CRITICAL_SECTION PSUTIL_CRITICAL_SECTION;
#define NT_FACILITY_MASK 0xfff
#define NT_FACILITY_SHIFT 16
#define NT_FACILITY(Status) \
((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK)
#define NT_NTWIN32(status) (NT_FACILITY(Status) == FACILITY_WIN32)
#define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff)
// A wrapper around GetModuleHandle and GetProcAddress.
PVOID
psutil_GetProcAddress(LPCSTR libname, LPCSTR procname) {
HMODULE mod;
FARPROC addr;
if ((mod = GetModuleHandleA(libname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, libname);
return NULL;
}
if ((addr = GetProcAddress(mod, procname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, procname);
return NULL;
}
return addr;
}
// A wrapper around LoadLibrary and GetProcAddress.
PVOID
psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname) {
HMODULE mod;
FARPROC addr;
Py_BEGIN_ALLOW_THREADS
mod = LoadLibraryA(libname);
Py_END_ALLOW_THREADS
if (mod == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, libname);
return NULL;
}
if ((addr = GetProcAddress(mod, procname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, procname);
FreeLibrary(mod);
return NULL;
}
// Causes crash.
// FreeLibrary(mod);
return addr;
}
/*
* Convert a NTSTATUS value to a Win32 error code and set the proper
* Python exception.
*/
PVOID
psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall) {
ULONG err;
char fullmsg[1024];
if (NT_NTWIN32(Status))
err = WIN32_FROM_NTSTATUS(Status);
else
err = RtlNtStatusToDosErrorNoTeb(Status);
// if (GetLastError() != 0)
// err = GetLastError();
sprintf(fullmsg, "(originated from %s)", syscall);
return PyErr_SetFromWindowsErrWithFilename(err, fullmsg);
}
static int
psutil_loadlibs() {
// --- Mandatory
NtQuerySystemInformation = psutil_GetProcAddressFromLib(
"ntdll.dll", "NtQuerySystemInformation");
if (! NtQuerySystemInformation)
return 1;
NtQueryInformationProcess = psutil_GetProcAddress(
"ntdll.dll", "NtQueryInformationProcess");
if (! NtQueryInformationProcess)
return 1;
NtSetInformationProcess = psutil_GetProcAddress(
"ntdll.dll", "NtSetInformationProcess");
if (! NtSetInformationProcess)
return 1;
WinStationQueryInformationW = psutil_GetProcAddressFromLib(
"winsta.dll", "WinStationQueryInformationW");
if (! WinStationQueryInformationW)
return 1;
NtQueryObject = psutil_GetProcAddressFromLib(
"ntdll.dll", "NtQueryObject");
if (! NtQueryObject)
return 1;
RtlIpv4AddressToStringA = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlIpv4AddressToStringA");
if (! RtlIpv4AddressToStringA)
return 1;
GetExtendedTcpTable = psutil_GetProcAddressFromLib(
"iphlpapi.dll", "GetExtendedTcpTable");
if (! GetExtendedTcpTable)
return 1;
GetExtendedUdpTable = psutil_GetProcAddressFromLib(
"iphlpapi.dll", "GetExtendedUdpTable");
if (! GetExtendedUdpTable)
return 1;
RtlGetVersion = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlGetVersion");
if (! RtlGetVersion)
return 1;
NtSuspendProcess = psutil_GetProcAddressFromLib(
"ntdll", "NtSuspendProcess");
if (! NtSuspendProcess)
return 1;
NtResumeProcess = psutil_GetProcAddressFromLib(
"ntdll", "NtResumeProcess");
if (! NtResumeProcess)
return 1;
NtQueryVirtualMemory = psutil_GetProcAddressFromLib(
"ntdll", "NtQueryVirtualMemory");
if (! NtQueryVirtualMemory)
return 1;
RtlNtStatusToDosErrorNoTeb = psutil_GetProcAddressFromLib(
"ntdll", "RtlNtStatusToDosErrorNoTeb");
if (! RtlNtStatusToDosErrorNoTeb)
return 1;
GetTickCount64 = psutil_GetProcAddress(
"kernel32", "GetTickCount64");
if (! GetTickCount64)
return 1;
RtlIpv6AddressToStringA = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlIpv6AddressToStringA");
if (! RtlIpv6AddressToStringA)
return 1;
// --- Optional
// minimum requirement: Win 7
GetActiveProcessorCount = psutil_GetProcAddress(
"kernel32", "GetActiveProcessorCount");
// minumum requirement: Win 7
GetLogicalProcessorInformationEx = psutil_GetProcAddressFromLib(
"kernel32", "GetLogicalProcessorInformationEx");
PyErr_Clear();
return 0;
}
static int
psutil_set_winver() {
RTL_OSVERSIONINFOEXW versionInfo;
ULONG maj;
ULONG min;
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
memset(&versionInfo, 0, sizeof(RTL_OSVERSIONINFOEXW));
RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo);
maj = versionInfo.dwMajorVersion;
min = versionInfo.dwMinorVersion;
if (maj == 6 && min == 0)
PSUTIL_WINVER = PSUTIL_WINDOWS_VISTA; // or Server 2008
else if (maj == 6 && min == 1)
PSUTIL_WINVER = PSUTIL_WINDOWS_7;
else if (maj == 6 && min == 2)
PSUTIL_WINVER = PSUTIL_WINDOWS_8;
else if (maj == 6 && min == 3)
PSUTIL_WINVER = PSUTIL_WINDOWS_8_1;
else if (maj == 10 && min == 0)
PSUTIL_WINVER = PSUTIL_WINDOWS_10;
else
PSUTIL_WINVER = PSUTIL_WINDOWS_NEW;
return 0;
}
int
psutil_load_globals() {
if (psutil_loadlibs() != 0)
return 1;
if (psutil_set_winver() != 0)
return 1;
GetSystemInfo(&PSUTIL_SYSTEM_INFO);
InitializeCriticalSection(&PSUTIL_CRITICAL_SECTION);
return 0;
}
/*
* Convert the hi and lo parts of a FILETIME structure or a LARGE_INTEGER
* to a UNIX time.
* A FILETIME contains a 64-bit value representing the number of
* 100-nanosecond intervals since January 1, 1601 (UTC).
* A UNIX time is the number of seconds that have elapsed since the
* UNIX epoch, that is the time 00:00:00 UTC on 1 January 1970.
*/
static double
_to_unix_time(ULONGLONG hiPart, ULONGLONG loPart) {
ULONGLONG ret;
// 100 nanosecond intervals since January 1, 1601.
ret = hiPart << 32;
ret += loPart;
// Change starting time to the Epoch (00:00:00 UTC, January 1, 1970).
ret -= 116444736000000000ull;
// Convert nano secs to secs.
return (double) ret / 10000000ull;
}
double
psutil_FiletimeToUnixTime(FILETIME ft) {
return _to_unix_time((ULONGLONG)ft.dwHighDateTime,
(ULONGLONG)ft.dwLowDateTime);
}
double
psutil_LargeIntegerToUnixTime(LARGE_INTEGER li) {
return _to_unix_time((ULONGLONG)li.HighPart,
(ULONGLONG)li.LowPart);
}
#endif // PSUTIL_WINDOWS

Просмотреть файл

@ -4,28 +4,136 @@
* found in the LICENSE file.
*/
#ifndef PSUTIL_PSUTIL_COMMON_H
#define PSUTIL_PSUTIL_COMMON_H
#include <Python.h>
// ====================================================================
// --- Global vars / constants
// ====================================================================
extern int PSUTIL_TESTING;
extern int PSUTIL_DEBUG;
// a signaler for connections without an actual status
static const int PSUTIL_CONN_NONE = 128;
// ====================================================================
// --- Backward compatibility with missing Python.h APIs
// ====================================================================
#if PY_MAJOR_VERSION < 3
PyObject* PyUnicode_DecodeFSDefault(char *s);
PyObject* PyUnicode_DecodeFSDefaultAndSize(char *s, Py_ssize_t size);
// On Python 2 we just return a plain byte string, which is never
// supposed to raise decoding errors, see:
// https://github.com/giampaolo/psutil/issues/1040
#define PyUnicode_DecodeFSDefault PyString_FromString
#define PyUnicode_DecodeFSDefaultAndSize PyString_FromStringAndSize
#endif
#if defined(PSUTIL_WINDOWS) && \
defined(PYPY_VERSION) && \
!defined(PyErr_SetFromWindowsErrWithFilename)
PyObject *PyErr_SetFromWindowsErrWithFilename(int ierr,
const char *filename);
#endif
// --- _Py_PARSE_PID
// SIZEOF_INT|LONG is missing on Linux + PyPy (only?).
// SIZEOF_PID_T is missing on Windows + Python2.
// In this case we guess it from setup.py. It's not 100% bullet proof,
// If wrong we'll probably get compiler warnings.
// FWIW on all UNIX platforms I've seen pid_t is defined as an int.
// _getpid() on Windows also returns an int.
#if !defined(SIZEOF_INT)
#define SIZEOF_INT 4
#endif
#if !defined(SIZEOF_LONG)
#define SIZEOF_LONG 8
#endif
#if !defined(SIZEOF_PID_T)
#define SIZEOF_PID_T PSUTIL_SIZEOF_PID_T // set as a macro in setup.py
#endif
// _Py_PARSE_PID is Python 3 only, but since it's private make sure it's
// always present.
#ifndef _Py_PARSE_PID
#if SIZEOF_PID_T == SIZEOF_INT
#define _Py_PARSE_PID "i"
#elif SIZEOF_PID_T == SIZEOF_LONG
#define _Py_PARSE_PID "l"
#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
#define _Py_PARSE_PID "L"
#else
#error "_Py_PARSE_PID: sizeof(pid_t) is neither sizeof(int), "
"sizeof(long) or sizeof(long long)"
#endif
#endif
// Python 2 or PyPy on Windows
#ifndef PyLong_FromPid
#if ((SIZEOF_PID_T == SIZEOF_INT) || (SIZEOF_PID_T == SIZEOF_LONG))
#if PY_MAJOR_VERSION >= 3
#define PyLong_FromPid PyLong_FromLong
#else
#define PyLong_FromPid PyInt_FromLong
#endif
#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
#define PyLong_FromPid PyLong_FromLongLong
#else
#error "PyLong_FromPid: sizeof(pid_t) is neither sizeof(int), "
"sizeof(long) or sizeof(long long)"
#endif
#endif
// ====================================================================
// --- Custom exceptions
// ====================================================================
PyObject* AccessDenied(const char *msg);
PyObject* NoSuchProcess(const char *msg);
PyObject* PyErr_SetFromOSErrnoWithSyscall(const char *syscall);
// ====================================================================
// --- Global utils
// ====================================================================
PyObject* psutil_set_testing(PyObject *self, PyObject *args);
void psutil_debug(const char* format, ...);
int psutil_setup(void);
#endif // PSUTIL_PSUTIL_COMMON_H
// ====================================================================
// --- Windows
// ====================================================================
#ifdef PSUTIL_WINDOWS
#include <windows.h>
// make it available to any file which includes this module
#include "arch/windows/ntextapi.h"
extern int PSUTIL_WINVER;
extern SYSTEM_INFO PSUTIL_SYSTEM_INFO;
extern CRITICAL_SECTION PSUTIL_CRITICAL_SECTION;
#define PSUTIL_WINDOWS_VISTA 60
#define PSUTIL_WINDOWS_7 61
#define PSUTIL_WINDOWS_8 62
#define PSUTIL_WINDOWS_8_1 63
#define PSUTIL_WINDOWS_10 100
#define PSUTIL_WINDOWS_NEW MAXLONG
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define MALLOC_ZERO(x) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
#define LO_T 1e-7
#define HI_T 429.4967296
#ifndef AF_INET6
#define AF_INET6 23
#endif
int psutil_load_globals();
PVOID psutil_GetProcAddress(LPCSTR libname, LPCSTR procname);
PVOID psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname);
PVOID psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall);
double psutil_FiletimeToUnixTime(FILETIME ft);
double psutil_LargeIntegerToUnixTime(LARGE_INTEGER li);
#endif

Просмотреть файл

@ -54,6 +54,11 @@ static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
#include <sys/resource.h>
#endif
// Should exist starting from CentOS 6 (year 2011).
#ifdef CPU_ALLOC
#define PSUTIL_HAVE_CPU_AFFINITY
#endif
#include "_psutil_common.h"
#include "_psutil_posix.h"
@ -92,9 +97,9 @@ ioprio_set(int which, int who, int ioprio) {
*/
static PyObject *
psutil_proc_ioprio_get(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int ioprio, ioclass, iodata;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
if (ioprio == -1)
@ -112,12 +117,14 @@ psutil_proc_ioprio_get(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_ioprio_set(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int ioprio, ioclass, iodata;
int retval;
if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata))
if (! PyArg_ParseTuple(
args, _Py_PARSE_PID "ii", &pid, &ioclass, &iodata)) {
return NULL;
}
ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata);
retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio);
if (retval == -1)
@ -135,15 +142,17 @@ psutil_proc_ioprio_set(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_linux_prlimit(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int ret, resource;
struct rlimit old, new;
struct rlimit *newp = NULL;
PyObject *py_soft = NULL;
PyObject *py_hard = NULL;
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &py_soft, &py_hard))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i|OO", &pid, &resource,
&py_soft, &py_hard)) {
return NULL;
}
// get
if (py_soft == NULL && py_hard == NULL) {
@ -195,7 +204,7 @@ static PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args) {
FILE *file = NULL;
struct mntent *entry;
const char *mtab_path;
char *mtab_path;
PyObject *py_dev = NULL;
PyObject *py_mountp = NULL;
PyObject *py_tuple = NULL;
@ -236,9 +245,9 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
Py_CLEAR(py_dev);
Py_CLEAR(py_mountp);
Py_CLEAR(py_tuple);
}
endmntent(file);
return py_retlist;
@ -279,21 +288,18 @@ psutil_linux_sysinfo(PyObject *self, PyObject *args) {
/*
* Return process CPU affinity as a Python list
* The dual implementation exists because of:
* https://github.com/giampaolo/psutil/issues/536
*/
#ifdef CPU_ALLOC
#ifdef PSUTIL_HAVE_CPU_AFFINITY
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
int cpu, ncpus, count, cpucount_s;
long pid;
pid_t pid;
size_t setsize;
cpu_set_t *mask = NULL;
PyObject *py_list = NULL;
if (!PyArg_ParseTuple(args, "l", &pid))
if (!PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
ncpus = NCPUS_START;
while (1) {
@ -347,50 +353,8 @@ error:
Py_XDECREF(py_list);
return NULL;
}
#else
/*
* Alternative implementation in case CPU_ALLOC is not defined.
*/
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) {
cpu_set_t cpuset;
unsigned int len = sizeof(cpu_set_t);
long pid;
int i;
PyObject* py_retlist = NULL;
PyObject *py_cpu_num = NULL;
if (!PyArg_ParseTuple(args, "l", &pid))
return NULL;
CPU_ZERO(&cpuset);
if (sched_getaffinity(pid, len, &cpuset) < 0)
return PyErr_SetFromErrno(PyExc_OSError);
py_retlist = PyList_New(0);
if (py_retlist == NULL)
goto error;
for (i = 0; i < CPU_SETSIZE; ++i) {
if (CPU_ISSET(i, &cpuset)) {
py_cpu_num = Py_BuildValue("i", i);
if (py_cpu_num == NULL)
goto error;
if (PyList_Append(py_retlist, py_cpu_num))
goto error;
Py_DECREF(py_cpu_num);
}
}
return py_retlist;
error:
Py_XDECREF(py_cpu_num);
Py_XDECREF(py_retlist);
return NULL;
}
#endif
/*
* Set process CPU affinity; expects a bitmask
*/
@ -398,12 +362,12 @@ static PyObject *
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
cpu_set_t cpu_set;
size_t len;
long pid;
pid_t pid;
int i, seq_len;
PyObject *py_cpu_set;
PyObject *py_cpu_seq = NULL;
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &py_cpu_set))
return NULL;
if (!PySequence_Check(py_cpu_set)) {
@ -432,7 +396,6 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
CPU_SET(value, &cpu_set);
}
len = sizeof(cpu_set);
if (sched_setaffinity(pid, len, &cpu_set)) {
PyErr_SetFromErrno(PyExc_OSError);
@ -447,6 +410,7 @@ error:
Py_DECREF(py_cpu_seq);
return NULL;
}
#endif /* PSUTIL_HAVE_CPU_AFFINITY */
/*
@ -481,8 +445,9 @@ psutil_users(PyObject *self, PyObject *args) {
py_hostname = PyUnicode_DecodeFSDefault(ut->ut_host);
if (! py_hostname)
goto error;
py_tuple = Py_BuildValue(
"(OOOfOi)",
"OOOfO" _Py_PARSE_PID,
py_username, // username
py_tty, // tty
py_hostname, // hostname
@ -494,10 +459,10 @@ psutil_users(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
}
endutent();
return py_retlist;
@ -577,10 +542,10 @@ error:
/*
* Define the psutil C module methods and initialize the module.
* Module init.
*/
static PyMethodDef
PsutilMethods[] = {
static PyMethodDef mod_methods[] = {
// --- per-process functions
#if PSUTIL_HAVE_IOPRIO
@ -589,10 +554,12 @@ PsutilMethods[] = {
{"proc_ioprio_set", psutil_proc_ioprio_set, METH_VARARGS,
"Set process I/O priority"},
#endif
#ifdef PSUTIL_HAVE_CPU_AFFINITY
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
"Return process CPU affinity as a Python long (the bitmask)."},
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
"Set process CPU affinity; expects a bitmask."},
#endif
// --- system related functions
@ -612,7 +579,6 @@ PsutilMethods[] = {
{"linux_prlimit", psutil_linux_prlimit, METH_VARARGS,
"Get or set process resource limits."},
#endif
// --- others
{"set_testing", psutil_set_testing, METH_NOARGS,
"Set psutil in testing mode"},
@ -620,75 +586,51 @@ PsutilMethods[] = {
{NULL, NULL, 0, NULL}
};
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
#endif
#define INITERR return NULL
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_psutil_linux",
NULL,
-1,
mod_methods,
NULL,
NULL,
NULL,
NULL
};
static int
psutil_linux_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
PyObject *PyInit__psutil_linux(void)
#else /* PY_MAJOR_VERSION */
#define INITERR return
static int
psutil_linux_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef
moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_linux",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_linux_traverse,
psutil_linux_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__psutil_linux(void)
#else
#define INITERROR return
void init_psutil_linux(void)
#endif
void init_psutil_linux(void)
#endif /* PY_MAJOR_VERSION */
{
PyObject *v;
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *mod = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_linux", PsutilMethods);
PyObject *mod = Py_InitModule("_psutil_linux", mod_methods);
#endif
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION)) INITERR;
#if PSUTIL_HAVE_PRLIMIT
PyModule_AddIntConstant(module, "RLIMIT_AS", RLIMIT_AS);
PyModule_AddIntConstant(module, "RLIMIT_CORE", RLIMIT_CORE);
PyModule_AddIntConstant(module, "RLIMIT_CPU", RLIMIT_CPU);
PyModule_AddIntConstant(module, "RLIMIT_DATA", RLIMIT_DATA);
PyModule_AddIntConstant(module, "RLIMIT_FSIZE", RLIMIT_FSIZE);
PyModule_AddIntConstant(module, "RLIMIT_LOCKS", RLIMIT_LOCKS);
PyModule_AddIntConstant(module, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
PyModule_AddIntConstant(module, "RLIMIT_NOFILE", RLIMIT_NOFILE);
PyModule_AddIntConstant(module, "RLIMIT_NPROC", RLIMIT_NPROC);
PyModule_AddIntConstant(module, "RLIMIT_RSS", RLIMIT_RSS);
PyModule_AddIntConstant(module, "RLIMIT_STACK", RLIMIT_STACK);
if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR;
if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR;
#if defined(HAVE_LONG_LONG)
if (sizeof(RLIM_INFINITY) > sizeof(long)) {
@ -699,32 +641,33 @@ void init_psutil_linux(void)
v = PyLong_FromLong((long) RLIM_INFINITY);
}
if (v) {
PyModule_AddObject(module, "RLIM_INFINITY", v);
PyModule_AddObject(mod, "RLIM_INFINITY", v);
}
#ifdef RLIMIT_MSGQUEUE
PyModule_AddIntConstant(module, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE);
if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR;
#endif
#ifdef RLIMIT_NICE
PyModule_AddIntConstant(module, "RLIMIT_NICE", RLIMIT_NICE);
if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR;
#endif
#ifdef RLIMIT_RTPRIO
PyModule_AddIntConstant(module, "RLIMIT_RTPRIO", RLIMIT_RTPRIO);
if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR;
#endif
#ifdef RLIMIT_RTTIME
PyModule_AddIntConstant(module, "RLIMIT_RTTIME", RLIMIT_RTTIME);
if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR;
#endif
#ifdef RLIMIT_SIGPENDING
PyModule_AddIntConstant(module, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING);
if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING))
INITERR;
#endif
#endif
PyModule_AddIntConstant(module, "DUPLEX_HALF", DUPLEX_HALF);
PyModule_AddIntConstant(module, "DUPLEX_FULL", DUPLEX_FULL);
PyModule_AddIntConstant(module, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN);
if (PyModule_AddIntConstant(mod, "DUPLEX_HALF", DUPLEX_HALF)) INITERR;
if (PyModule_AddIntConstant(mod, "DUPLEX_FULL", DUPLEX_FULL)) INITERR;
if (PyModule_AddIntConstant(mod, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN)) INITERR;
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
#if PY_MAJOR_VERSION >= 3
return module;
return mod;
#endif
}

255
third_party/python/psutil/psutil/_psutil_osx.c поставляемый
Просмотреть файл

@ -88,15 +88,15 @@ psutil_sys_vminfo(vm_statistics_data_t *vmstat) {
* https://github.com/giampaolo/psutil/issues/1291#issuecomment-396062519
*/
int
psutil_task_for_pid(long pid, mach_port_t *task)
psutil_task_for_pid(pid_t pid, mach_port_t *task)
{
// See: https://github.com/giampaolo/psutil/issues/1181
kern_return_t err = KERN_SUCCESS;
err = task_for_pid(mach_task_self(), (pid_t)pid, task);
err = task_for_pid(mach_task_self(), pid, task);
if (err != KERN_SUCCESS) {
if (psutil_pid_exists(pid) == 0)
NoSuchProcess("task_for_pid() failed");
NoSuchProcess("task_for_pid");
else if (psutil_is_zombie(pid) == 1)
PyErr_SetString(ZombieProcessError, "task_for_pid() failed");
else {
@ -104,7 +104,7 @@ psutil_task_for_pid(long pid, mach_port_t *task)
"task_for_pid() failed (pid=%ld, err=%i, errno=%i, msg='%s'); "
"setting AccessDenied()",
pid, err, errno, mach_error_string(err));
AccessDenied("task_for_pid() failed");
AccessDenied("task_for_pid");
}
return 1;
}
@ -133,12 +133,12 @@ psutil_pids(PyObject *self, PyObject *args) {
// save the address of proclist so we can free it later
orig_address = proclist;
for (idx = 0; idx < num_processes; idx++) {
py_pid = Py_BuildValue("i", proclist->kp_proc.p_pid);
py_pid = PyLong_FromPid(proclist->kp_proc.p_pid);
if (! py_pid)
goto error;
if (PyList_Append(py_retlist, py_pid))
goto error;
Py_DECREF(py_pid);
Py_CLEAR(py_pid);
proclist++;
}
free(orig_address);
@ -164,12 +164,12 @@ error:
*/
static PyObject *
psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
struct kinfo_proc kp;
PyObject *py_name;
PyObject *py_retlist;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -183,8 +183,8 @@ psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
}
py_retlist = Py_BuildValue(
"lllllllidiO",
(long)kp.kp_eproc.e_ppid, // (long) ppid
_Py_PARSE_PID "llllllidiO",
kp.kp_eproc.e_ppid, // (pid_t) ppid
(long)kp.kp_eproc.e_pcred.p_ruid, // (long) real uid
(long)kp.kp_eproc.e_ucred.cr_uid, // (long) effective uid
(long)kp.kp_eproc.e_pcred.p_svuid, // (long) saved uid
@ -215,10 +215,10 @@ psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_pidtaskinfo_oneshot(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
struct proc_taskinfo pti;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti)) <= 0)
return NULL;
@ -250,10 +250,10 @@ psutil_proc_pidtaskinfo_oneshot(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_name(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -267,10 +267,10 @@ psutil_proc_name(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
struct proc_vnodepathinfo pathinfo;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_proc_pidinfo(
@ -288,17 +288,17 @@ psutil_proc_cwd(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_exe(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
char buf[PATH_MAX];
int ret;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
errno = 0;
ret = proc_pidpath((pid_t)pid, &buf, sizeof(buf));
ret = proc_pidpath(pid, &buf, sizeof(buf));
if (ret == 0) {
if (pid == 0)
AccessDenied("");
AccessDenied("automatically set for PID 0");
else
psutil_raise_for_pid(pid, "proc_pidpath()");
return NULL;
@ -312,10 +312,10 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_cmdline(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
PyObject *py_retlist = NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
// get the commandline, defined in arch/osx/process_info.c
@ -329,10 +329,10 @@ psutil_proc_cmdline(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_proc_environ(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
PyObject *py_retdict = NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
// get the environment block, defined in arch/osx/process_info.c
@ -422,7 +422,7 @@ psutil_in_shared_region(mach_vm_address_t addr, cpu_type_t type) {
*/
static PyObject *
psutil_proc_memory_uss(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
size_t len;
cpu_type_t cpu_type;
size_t private_pages = 0;
@ -435,7 +435,7 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) {
vm_region_top_info_data_t info;
mach_port_t object_name;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_task_for_pid(pid, &task) != 0)
@ -653,7 +653,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
Py_CLEAR(py_cputime);
}
ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
@ -841,9 +841,9 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
Py_CLEAR(py_dev);
Py_CLEAR(py_mountp);
Py_CLEAR(py_tuple);
}
free(fs);
@ -865,7 +865,7 @@ error:
*/
static PyObject *
psutil_proc_threads(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int err, ret;
kern_return_t kr;
unsigned int info_count = TASK_BASIC_INFO_COUNT;
@ -882,7 +882,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
if (psutil_task_for_pid(pid, &task) != 0)
@ -894,7 +894,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
if (err != KERN_SUCCESS) {
// errcode 4 is "invalid argument" (access denied)
if (err == 4) {
AccessDenied("");
AccessDenied("task_info");
}
else {
// otherwise throw a runtime error with appropriate error code
@ -911,7 +911,6 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
}
for (j = 0; j < thread_count; j++) {
py_tuple = NULL;
thread_info_count = THREAD_INFO_MAX;
kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
(thread_info_t)thinfo_basic, &thread_info_count);
@ -934,7 +933,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
ret = vm_deallocate(task, (vm_address_t)thread_list,
@ -969,7 +968,7 @@ error:
*/
static PyObject *
psutil_proc_open_files(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int pidinfo_result;
int iterations;
int i;
@ -986,7 +985,7 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
pidinfo_result = psutil_proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
@ -1043,10 +1042,8 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
py_tuple = NULL;
Py_DECREF(py_path);
py_path = NULL;
Py_CLEAR(py_tuple);
Py_CLEAR(py_path);
// --- /construct python list
}
}
@ -1073,7 +1070,7 @@ error:
*/
static PyObject *
psutil_proc_connections(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int pidinfo_result;
int iterations;
int i;
@ -1093,8 +1090,10 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, &py_af_filter,
&py_type_filter)) {
goto error;
}
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
@ -1127,7 +1126,7 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) {
errno = 0;
nb = proc_pidfdinfo((pid_t)pid, fdp_pointer->proc_fd,
nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd,
PROC_PIDFDSOCKETINFO, &si, sizeof(si));
// --- errors checking
@ -1226,7 +1225,7 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
else if (family == AF_UNIX) {
py_laddr = PyUnicode_DecodeFSDefault(
@ -1248,9 +1247,9 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_DECREF(py_laddr);
Py_DECREF(py_raddr);
Py_CLEAR(py_tuple);
Py_CLEAR(py_laddr);
Py_CLEAR(py_raddr);
}
}
}
@ -1275,22 +1274,22 @@ error:
*/
static PyObject *
psutil_proc_num_fds(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int pidinfo_result;
int num;
struct proc_fdinfo *fds_pointer;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, NULL, 0);
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
if (pidinfo_result <= 0)
return PyErr_SetFromErrno(PyExc_OSError);
fds_pointer = malloc(pidinfo_result);
if (fds_pointer == NULL)
return PyErr_NoMemory();
pidinfo_result = proc_pidinfo((pid_t)pid, PROC_PIDLISTFDS, 0, fds_pointer,
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
pidinfo_result);
if (pidinfo_result <= 0) {
free(fds_pointer);
@ -1370,7 +1369,7 @@ psutil_net_io_counters(PyObject *self, PyObject *args) {
goto error;
if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
Py_CLEAR(py_ifc_info);
}
else {
continue;
@ -1543,7 +1542,7 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
goto error;
if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info))
goto error;
Py_DECREF(py_disk_info);
Py_CLEAR(py_disk_info);
CFRelease(parent_dict);
IOObjectRelease(parent);
@ -1605,10 +1604,10 @@ psutil_users(PyObject *self, PyObject *args) {
endutxent();
goto error;
}
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
}
endutxent();
@ -1745,8 +1744,7 @@ error:
/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] = {
static PyMethodDef mod_methods[] = {
// --- per-process functions
{"proc_kinfo_oneshot", psutil_proc_kinfo_oneshot, METH_VARARGS,
@ -1816,96 +1814,93 @@ PsutilMethods[] = {
};
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
#endif
#define INITERR return NULL
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_psutil_osx",
NULL,
-1,
mod_methods,
NULL,
NULL,
NULL,
NULL
};
static int
psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
PyObject *PyInit__psutil_osx(void)
#else /* PY_MAJOR_VERSION */
#define INITERR return
static int
psutil_osx_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_osx",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_osx_traverse,
psutil_osx_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__psutil_osx(void)
#else
#define INITERROR return
void
init_psutil_osx(void)
#endif
void init_psutil_osx(void)
#endif /* PY_MAJOR_VERSION */
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *mod = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
PyObject *mod = Py_InitModule("_psutil_osx", mod_methods);
#endif
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
if (psutil_setup() != 0)
INITERROR;
INITERR;
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
if (PyModule_AddIntConstant(mod, "version", PSUTIL_VERSION))
INITERR;
// process status constants, defined in:
// http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149
PyModule_AddIntConstant(module, "SIDL", SIDL);
PyModule_AddIntConstant(module, "SRUN", SRUN);
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
PyModule_AddIntConstant(module, "SZOMB", SZOMB);
if (PyModule_AddIntConstant(mod, "SIDL", SIDL))
INITERR;
if (PyModule_AddIntConstant(mod, "SRUN", SRUN))
INITERR;
if (PyModule_AddIntConstant(mod, "SSLEEP", SSLEEP))
INITERR;
if (PyModule_AddIntConstant(mod, "SSTOP", SSTOP))
INITERR;
if (PyModule_AddIntConstant(mod, "SZOMB", SZOMB))
INITERR;
// connection status constants
PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED);
PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING);
PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT);
PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN);
PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED);
PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT);
PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED);
PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1);
PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2);
PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK);
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
if (PyModule_AddIntConstant(mod, "TCPS_CLOSED", TCPS_CLOSED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_CLOSING", TCPS_CLOSING))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_LISTEN", TCPS_LISTEN))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_ESTABLISHED", TCPS_ESTABLISHED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_SYN_SENT", TCPS_SYN_SENT))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_LAST_ACK", TCPS_LAST_ACK))
INITERR;
if (PyModule_AddIntConstant(mod, "TCPS_TIME_WAIT", TCPS_TIME_WAIT))
INITERR;
if (PyModule_AddIntConstant(mod, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE))
INITERR;
// Exception.
ZombieProcessError = PyErr_NewException(
"_psutil_osx.ZombieProcessError", NULL, NULL);
if (ZombieProcessError == NULL)
INITERR;
Py_INCREF(ZombieProcessError);
PyModule_AddObject(module, "ZombieProcessError", ZombieProcessError);
if (PyModule_AddObject(mod, "ZombieProcessError", ZombieProcessError)) {
Py_DECREF(ZombieProcessError);
INITERR;
}
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
#if PY_MAJOR_VERSION >= 3
return module;
return mod;
#endif
}

Просмотреть файл

@ -51,7 +51,7 @@
* -1: error (Python exception is set)
*/
int
psutil_pid_exists(long pid) {
psutil_pid_exists(pid_t pid) {
int ret;
// No negative PID exists, plus -1 is an alias for sending signal
@ -71,12 +71,7 @@ psutil_pid_exists(long pid) {
#endif
}
#if defined(PSUTIL_OSX)
ret = kill((pid_t)pid , 0);
#else
ret = kill(pid , 0);
#endif
if (ret == 0)
return 1;
else {
@ -111,23 +106,14 @@ psutil_pid_exists(long pid) {
* If none of this is true we giveup and raise RuntimeError(msg).
* This will always set a Python exception and return NULL.
*/
int
psutil_raise_for_pid(long pid, char *syscall_name) {
// Set exception to AccessDenied if pid exists else NoSuchProcess.
if (errno != 0) {
// Unlikely we get here.
PyErr_SetFromErrno(PyExc_OSError);
return 0;
}
else if (psutil_pid_exists(pid) == 0) {
psutil_debug("%s syscall failed and PID %i no longer exists; "
"assume NoSuchProcess", syscall_name, pid);
NoSuchProcess("");
}
else {
PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall_name);
}
return 0;
void
psutil_raise_for_pid(long pid, char *syscall) {
if (errno != 0) // unlikely
PyErr_SetFromOSErrnoWithSyscall(syscall);
else if (psutil_pid_exists(pid) == 0)
NoSuchProcess(syscall);
else
PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall);
}
@ -136,11 +122,11 @@ psutil_raise_for_pid(long pid, char *syscall_name) {
*/
static PyObject *
psutil_posix_getpriority(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int priority;
errno = 0;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
#ifdef PSUTIL_OSX
@ -159,11 +145,11 @@ psutil_posix_getpriority(PyObject *self, PyObject *args) {
*/
static PyObject *
psutil_posix_setpriority(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int priority;
int retval;
if (! PyArg_ParseTuple(args, "li", &pid, &priority))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &priority))
return NULL;
#ifdef PSUTIL_OSX
@ -206,8 +192,8 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) {
// XXX we get here on FreeBSD when processing 'lo' / AF_INET6
// broadcast. Not sure what to do other than returning None.
// ifconfig does not show anything BTW.
//PyErr_Format(PyExc_RuntimeError, gai_strerror(err));
//return NULL;
// PyErr_Format(PyExc_RuntimeError, gai_strerror(err));
// return NULL;
Py_INCREF(Py_None);
return Py_None;
}
@ -324,11 +310,11 @@ psutil_net_if_addrs(PyObject* self, PyObject* args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_DECREF(py_address);
Py_DECREF(py_netmask);
Py_DECREF(py_broadcast);
Py_DECREF(py_ptp);
Py_CLEAR(py_tuple);
Py_CLEAR(py_address);
Py_CLEAR(py_netmask);
Py_CLEAR(py_broadcast);
Py_CLEAR(py_ptp);
}
freeifaddrs(ifaddr);
@ -354,7 +340,7 @@ error:
static PyObject *
psutil_net_if_mtu(PyObject *self, PyObject *args) {
char *nic_name;
int sock = 0;
int sock = -1;
int ret;
#ifdef PSUTIL_SUNOS10
struct lifreq lifr;
@ -387,7 +373,7 @@ psutil_net_if_mtu(PyObject *self, PyObject *args) {
#endif
error:
if (sock != 0)
if (sock != -1)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}
@ -401,7 +387,7 @@ error:
static PyObject *
psutil_net_if_flags(PyObject *self, PyObject *args) {
char *nic_name;
int sock = 0;
int sock = -1;
int ret;
struct ifreq ifr;
@ -424,7 +410,7 @@ psutil_net_if_flags(PyObject *self, PyObject *args) {
return Py_BuildValue("O", Py_False);
error:
if (sock != 0)
if (sock != -1)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}
@ -579,7 +565,7 @@ int psutil_get_nic_speed(int ifm_active) {
static PyObject *
psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
char *nic_name;
int sock = 0;
int sock = -1;
int ret;
int duplex;
int speed;
@ -591,7 +577,7 @@ psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;
return PyErr_SetFromErrno(PyExc_OSError);
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
// speed / duplex
@ -614,20 +600,19 @@ psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
close(sock);
return Py_BuildValue("[ii]", duplex, speed);
error:
if (sock != 0)
close(sock);
return PyErr_SetFromErrno(PyExc_OSError);
}
#endif // net_if_stats() macOS/BSD implementation
#ifdef __cplusplus
extern "C" {
#endif
/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] = {
static PyMethodDef mod_methods[] = {
{"getpriority", psutil_posix_getpriority, METH_VARARGS,
"Return process priority"},
{"setpriority", psutil_posix_setpriority, METH_VARARGS,
@ -645,71 +630,48 @@ PsutilMethods[] = {
{NULL, NULL, 0, NULL}
};
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
#endif
#define INITERR return NULL
#ifdef __cplusplus
extern "C" {
#endif
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_psutil_posix",
NULL,
-1,
mod_methods,
NULL,
NULL,
NULL,
NULL
};
#if PY_MAJOR_VERSION >= 3
PyObject *PyInit__psutil_posix(void)
#else /* PY_MAJOR_VERSION */
#define INITERR return
static int
psutil_posix_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int
psutil_posix_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_posix",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_posix_traverse,
psutil_posix_clear,
NULL
};
#define INITERROR return NULL
PyMODINIT_FUNC PyInit__psutil_posix(void)
#else
#define INITERROR return
void init_psutil_posix(void)
#endif
void init_psutil_posix(void)
#endif /* PY_MAJOR_VERSION */
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *mod = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods);
PyObject *mod = Py_InitModule("_psutil_posix", mod_methods);
#endif
if (mod == NULL)
INITERR;
#if defined(PSUTIL_BSD) || \
defined(PSUTIL_OSX) || \
defined(PSUTIL_SUNOS) || \
defined(PSUTIL_AIX)
if (PyModule_AddIntConstant(mod, "AF_LINK", AF_LINK)) INITERR;
#endif
#if defined(PSUTIL_BSD) || defined(PSUTIL_OSX) || defined(PSUTIL_SUNOS) || defined(PSUTIL_AIX)
PyModule_AddIntConstant(module, "AF_LINK", AF_LINK);
#endif
if (module == NULL)
INITERROR;
if (mod == NULL)
INITERR;
#if PY_MAJOR_VERSION >= 3
return module;
return mod;
#endif
}

Просмотреть файл

@ -4,5 +4,5 @@
* found in the LICENSE file.
*/
int psutil_pid_exists(long pid);
void psutil_raise_for_pid(long pid, char *msg);
int psutil_pid_exists(pid_t pid);
void psutil_raise_for_pid(pid_t pid, char *msg);

Просмотреть файл

@ -12,12 +12,8 @@
/* fix compilation issue on SunOS 5.10, see:
* https://github.com/giampaolo/psutil/issues/421
* https://github.com/giampaolo/psutil/issues/1077
* http://us-east.manta.joyent.com/jmc/public/opensolaris/ARChive/PSARC/2010/111/materials/s10ceval.txt
*
* Because LEGACY_MIB_SIZE defined in the same file there is no way to make autoconfiguration =\
*/
#define NEW_MIB_COMPLIANT 1
#define _STRUCTURED_PROC 1
#include <Python.h>
@ -44,6 +40,14 @@
#include <sys/tihdr.h>
#include <stropts.h>
#include <inet/tcp.h>
#ifndef NEW_MIB_COMPLIANT
/*
* Solaris introduced NEW_MIB_COMPLIANT macro with Update 4.
* See https://github.com/giampaolo/psutil/issues/421
* Prior to Update 4, one has to include mib2 by hand.
*/
#include <inet/mib2.h>
#endif
#include <arpa/inet.h>
#include <net/if.h>
#include <math.h> // fabs()
@ -271,7 +275,7 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
goto error;
if (! info.pr_envp) {
AccessDenied("");
AccessDenied("/proc/pid/psinfo struct not set");
goto error;
}
@ -300,8 +304,8 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
if (PyDict_SetItem(py_retdict, py_envname, py_envval) < 0)
goto error;
Py_DECREF(py_envname);
Py_DECREF(py_envval);
Py_CLEAR(py_envname);
Py_CLEAR(py_envval);
}
psutil_free_cstrings_array(env, env_count);
@ -492,7 +496,7 @@ proc_io_counters(PyObject* self, PyObject* args) {
info.pr_inblk,
info.pr_oublk);
}
*/
*/
/*
@ -655,10 +659,10 @@ psutil_users(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_username);
Py_DECREF(py_tty);
Py_DECREF(py_hostname);
Py_DECREF(py_tuple);
Py_CLEAR(py_username);
Py_CLEAR(py_tty);
Py_CLEAR(py_hostname);
Py_CLEAR(py_tuple);
}
endutxent();
@ -714,9 +718,9 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_dev);
Py_DECREF(py_mountp);
Py_DECREF(py_tuple);
Py_CLEAR(py_dev);
Py_CLEAR(py_mountp);
Py_CLEAR(py_tuple);
}
fclose(file);
return py_retlist;
@ -767,8 +771,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
py_cputime = NULL;
Py_CLEAR(py_cputime);
}
}
@ -824,7 +827,7 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) {
if (PyDict_SetItemString(py_retdict, ksp->ks_name,
py_disk_info))
goto error;
Py_DECREF(py_disk_info);
Py_CLEAR(py_disk_info);
}
}
ksp = ksp->ks_next;
@ -959,8 +962,8 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_path);
Py_DECREF(py_tuple);
Py_CLEAR(py_path);
Py_CLEAR(py_tuple);
// increment pointer
p += 1;
@ -1075,7 +1078,7 @@ psutil_net_io_counters(PyObject *self, PyObject *args) {
goto error;
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
Py_CLEAR(py_ifc_info);
goto next;
next:
@ -1120,7 +1123,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
mib2_udp6Entry_t ude6;
#endif
char buf[512];
int i, flags, getcode, num_ent, state;
int i, flags, getcode, num_ent, state, ret;
char lip[INET6_ADDRSTRLEN], rip[INET6_ADDRSTRLEN];
int lport, rport;
int processed_pid;
@ -1147,7 +1150,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
goto error;
}
int ret = ioctl(sd, I_PUSH, "tcp");
ret = ioctl(sd, I_PUSH, "tcp");
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
@ -1273,7 +1276,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
}
#if defined(AF_INET6)
@ -1287,7 +1290,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
#ifdef NEW_MIB_COMPLIANT
processed_pid = tp6.tcp6ConnCreationProcess;
#else
processed_pid = 0;
processed_pid = 0;
#endif
if (pid != -1 && processed_pid != pid)
continue;
@ -1316,14 +1319,14 @@ psutil_net_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
}
#endif
// UDPv4
else if (mibhdr.level == MIB2_UDP || mibhdr.level == MIB2_UDP_ENTRY) {
num_ent = mibhdr.len / sizeof(mib2_udpEntry_t);
assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr.len);
assert(num_ent * sizeof(mib2_udpEntry_t) == mibhdr.len);
for (i = 0; i < num_ent; i++) {
memcpy(&ude, databuf.buf + i * sizeof ude, sizeof ude);
#ifdef NEW_MIB_COMPLIANT
@ -1355,7 +1358,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
}
#if defined(AF_INET6)
@ -1388,7 +1391,7 @@ psutil_net_connections(PyObject *self, PyObject *args) {
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
}
#endif
@ -1561,7 +1564,7 @@ psutil_net_if_stats(PyObject* self, PyObject* args) {
goto error;
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
Py_CLEAR(py_ifc_info);
}
}
@ -1748,7 +1751,14 @@ void init_psutil_sunos(void)
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
PyModule_AddIntConstant(module, "SIDL", SIDL);
PyModule_AddIntConstant(module, "SONPROC", SONPROC);
#ifdef SWAIT
PyModule_AddIntConstant(module, "SWAIT", SWAIT);
#else
/* sys/proc.h started defining SWAIT somewhere
* after Update 3 and prior to Update 5 included.
*/
PyModule_AddIntConstant(module, "SWAIT", 0);
#endif
PyModule_AddIntConstant(module, "PRNODEV", PRNODEV); // for process tty

Разница между файлами не показана из-за своего большого размера Загрузить разницу

258
third_party/python/psutil/psutil/_pswindows.py поставляемый
Просмотреть файл

@ -8,39 +8,24 @@ import contextlib
import errno
import functools
import os
import signal
import sys
import time
from collections import namedtuple
from . import _common
try:
from . import _psutil_windows as cext
except ImportError as err:
if str(err).lower().startswith("dll load failed") and \
sys.getwindowsversion()[0] < 6:
# We may get here if:
# 1) we are on an old Windows version
# 2) psutil was installed via pip + wheel
# See: https://github.com/giampaolo/psutil/issues/811
# It must be noted that psutil can still (kind of) work
# on outdated systems if compiled / installed from sources,
# but if we get here it means this this was a wheel (or exe).
msg = "this Windows version is too old (< Windows Vista); "
msg += "psutil 3.4.2 is the latest version which supports Windows "
msg += "2000, XP and 2003 server"
raise RuntimeError(msg)
else:
raise
from ._common import AccessDenied
from ._common import conn_tmap
from ._common import conn_to_ntuple
from ._common import debug
from ._common import ENCODING
from ._common import ENCODING_ERRS
from ._common import isfile_strict
from ._common import memoize
from ._common import memoize_when_activated
from ._common import NoSuchProcess
from ._common import parse_environ_block
from ._common import sockfam_to_enum
from ._common import socktype_to_enum
from ._common import TimeoutExpired
from ._common import usage_percent
from ._compat import long
from ._compat import lru_cache
@ -54,6 +39,22 @@ from ._psutil_windows import IDLE_PRIORITY_CLASS
from ._psutil_windows import NORMAL_PRIORITY_CLASS
from ._psutil_windows import REALTIME_PRIORITY_CLASS
try:
from . import _psutil_windows as cext
except ImportError as err:
if str(err).lower().startswith("dll load failed") and \
sys.getwindowsversion()[0] < 6:
# We may get here if:
# 1) we are on an old Windows version
# 2) psutil was installed via pip + wheel
# See: https://github.com/giampaolo/psutil/issues/811
msg = "this Windows version is too old (< Windows Vista); "
msg += "psutil 3.4.2 is the latest version which supports Windows "
msg += "2000, XP and 2003 server"
raise RuntimeError(msg)
else:
raise
if sys.version_info >= (3, 4):
import enum
else:
@ -79,9 +80,8 @@ __extra__all__ = [
# =====================================================================
CONN_DELETE_TCB = "DELETE_TCB"
HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_io_priority_get")
HAS_GETLOADAVG = hasattr(cext, "getloadavg")
ERROR_PARTIAL_COPY = 299
PYPY = '__pypy__' in sys.builtin_module_names
if enum is None:
AF_LINK = -1
@ -154,35 +154,6 @@ pinfo_map = dict(
mem_private=21,
)
# These objects get set on "import psutil" from the __init__.py
# file, see: https://github.com/giampaolo/psutil/issues/1402
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
# More values at: https://stackoverflow.com/a/20804735/376587
WIN_10 = (10, 0)
WIN_8 = (6, 2)
WIN_7 = (6, 1)
WIN_SERVER_2008 = (6, 0)
WIN_VISTA = (6, 0)
WIN_SERVER_2003 = (5, 2)
WIN_XP = (5, 1)
@lru_cache()
def get_winver():
"""Usage:
>>> if get_winver() <= WIN_VISTA:
... ...
"""
wv = sys.getwindowsversion()
return (wv.major, wv.minor)
IS_WIN_XP = get_winver() < WIN_VISTA
# =====================================================================
# --- named tuples
@ -227,7 +198,8 @@ def convert_dos_path(s):
"""
rawdrive = '\\'.join(s.split('\\')[:3])
driveletter = cext.win32_QueryDosDevice(rawdrive)
return os.path.join(driveletter, s[len(rawdrive):])
remainder = s[len(rawdrive):]
return os.path.join(driveletter, remainder)
def py2_strencode(s):
@ -354,21 +326,21 @@ def cpu_freq():
return [_common.scpufreq(float(curr), min_, float(max_))]
if HAS_GETLOADAVG:
_loadavg_inititialized = False
_loadavg_inititialized = False
def getloadavg():
"""Return the number of processes in the system run queue averaged
over the last 1, 5, and 15 minutes respectively as a tuple"""
global _loadavg_inititialized
if not _loadavg_inititialized:
cext.init_loadavg_counter()
_loadavg_inititialized = True
def getloadavg():
"""Return the number of processes in the system run queue averaged
over the last 1, 5, and 15 minutes respectively as a tuple"""
global _loadavg_inititialized
# Drop to 2 decimal points which is what Linux does
raw_loads = cext.getloadavg()
return tuple([round(load, 2) for load in raw_loads])
if not _loadavg_inititialized:
cext.init_loadavg_counter()
_loadavg_inititialized = True
# Drop to 2 decimal points which is what Linux does
raw_loads = cext.getloadavg()
return tuple([round(load, 2) for load in raw_loads])
# =====================================================================
@ -388,17 +360,8 @@ def net_connections(kind, _pid=-1):
ret = set()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
if laddr:
laddr = _common.addr(*laddr)
if raddr:
raddr = _common.addr(*raddr)
status = TCP_STATUSES[status]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
if _pid == -1:
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
else:
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, TCP_STATUSES,
pid=pid if _pid == -1 else None)
ret.add(nt)
return list(ret)
@ -719,6 +682,32 @@ def wrap_exceptions(fun):
return wrapper
def retry_error_partial_copy(fun):
"""Workaround for https://github.com/giampaolo/psutil/issues/875.
See: https://stackoverflow.com/questions/4457745#4457745
"""
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
delay = 0.0001
times = 33
for x in range(times): # retries for roughly 1 second
try:
return fun(self, *args, **kwargs)
except WindowsError as _:
err = _
if err.winerror == ERROR_PARTIAL_COPY:
time.sleep(delay)
delay = min(delay * 2, 0.04)
continue
else:
raise
else:
msg = "%s retried %s times, converted to AccessDenied as it's " \
"still returning %r" % (fun, times, err)
raise AccessDenied(pid=self.pid, name=self._name, msg=msg)
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
@ -732,14 +721,15 @@ class Process(object):
# --- oneshot() stuff
def oneshot_enter(self):
self.oneshot_info.cache_activate(self)
self._proc_info.cache_activate(self)
self.exe.cache_activate(self)
def oneshot_exit(self):
self.oneshot_info.cache_deactivate(self)
self._proc_info.cache_deactivate(self)
self.exe.cache_deactivate(self)
@wrap_exceptions
@memoize_when_activated
def oneshot_info(self):
def _proc_info(self):
"""Return multiple information about this process as a
raw tuple.
"""
@ -747,7 +737,6 @@ class Process(object):
assert len(ret) == len(pinfo_map)
return ret
@wrap_exceptions
def name(self):
"""Return process name, which on Windows is always the final
part of the executable.
@ -756,32 +745,33 @@ class Process(object):
# and process-hacker.
if self.pid == 0:
return "System Idle Process"
elif self.pid == 4:
if self.pid == 4:
return "System"
else:
try:
# Note: this will fail with AD for most PIDs owned
# by another user but it's faster.
return py2_strencode(os.path.basename(self.exe()))
except AccessDenied:
return py2_strencode(cext.proc_name(self.pid))
return os.path.basename(self.exe())
@wrap_exceptions
@memoize_when_activated
def exe(self):
# Dual implementation, see:
# https://github.com/giampaolo/psutil/pull/1413
if not IS_WIN_XP:
exe = cext.proc_exe(self.pid)
if PYPY:
try:
exe = cext.proc_exe(self.pid)
except WindowsError as err:
# 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens
# (perhaps PyPy's JIT delaying garbage collection of files?).
if err.errno == 24:
debug("%r forced into AccessDenied" % err)
raise AccessDenied(self.pid, self._name)
raise
else:
if self.pid in (0, 4):
# https://github.com/giampaolo/psutil/issues/414
# https://github.com/giampaolo/psutil/issues/528
raise AccessDenied(self.pid, self._name)
exe = cext.proc_exe(self.pid)
exe = convert_dos_path(exe)
return py2_strencode(exe)
if not PY3:
exe = py2_strencode(exe)
if exe.startswith('\\'):
return convert_dos_path(exe)
return exe # May be "Registry", "MemCompression", ...
@wrap_exceptions
@retry_error_partial_copy
def cmdline(self):
if cext.WINVER >= cext.WINDOWS_8_1:
# PEB method detects cmdline changes but requires more
@ -801,6 +791,7 @@ class Process(object):
return [py2_strencode(s) for s in ret]
@wrap_exceptions
@retry_error_partial_copy
def environ(self):
ustr = cext.proc_environ(self.pid)
if ustr and not PY3:
@ -820,7 +811,7 @@ class Process(object):
if is_permission_err(err):
# TODO: the C ext can probably be refactored in order
# to get this from cext.proc_info()
info = self.oneshot_info()
info = self._proc_info()
return (
info[pinfo_map['num_page_faults']],
info[pinfo_map['peak_wset']],
@ -863,7 +854,6 @@ class Process(object):
for addr, perm, path, rss in raw:
path = convert_dos_path(path)
if not PY3:
assert isinstance(path, unicode), type(path)
path = py2_strencode(path)
addr = hex(addr)
yield (addr, perm, path, rss)
@ -874,7 +864,16 @@ class Process(object):
@wrap_exceptions
def send_signal(self, sig):
os.kill(self.pid, sig)
if sig == signal.SIGTERM:
cext.proc_kill(self.pid)
# py >= 2.7
elif sig in (getattr(signal, "CTRL_C_EVENT", object()),
getattr(signal, "CTRL_BREAK_EVENT", object())):
os.kill(self.pid, sig)
else:
raise ValueError(
"only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
"are supported on Windows")
@wrap_exceptions
def wait(self, timeout=None):
@ -928,19 +927,19 @@ class Process(object):
@wrap_exceptions
def create_time(self):
# special case for kernel process PIDs; return system boot time
if self.pid in (0, 4):
return boot_time()
# Note: proc_times() not put under oneshot() 'cause create_time()
# is already cached by the main Process class.
try:
return cext.proc_create_time(self.pid)
user, system, created = cext.proc_times(self.pid)
return created
except OSError as err:
if is_permission_err(err):
return self.oneshot_info()[pinfo_map['create_time']]
return self._proc_info()[pinfo_map['create_time']]
raise
@wrap_exceptions
def num_threads(self):
return self.oneshot_info()[pinfo_map['num_threads']]
return self._proc_info()[pinfo_map['num_threads']]
@wrap_exceptions
def threads(self):
@ -954,11 +953,11 @@ class Process(object):
@wrap_exceptions
def cpu_times(self):
try:
user, system = cext.proc_cpu_times(self.pid)
user, system, created = cext.proc_times(self.pid)
except OSError as err:
if not is_permission_err(err):
raise
info = self.oneshot_info()
info = self._proc_info()
user = info[pinfo_map['user_time']]
system = info[pinfo_map['kernel_time']]
# Children user/system times are not retrievable (set to 0).
@ -973,6 +972,7 @@ class Process(object):
cext.proc_suspend_or_resume(self.pid, False)
@wrap_exceptions
@retry_error_partial_copy
def cwd(self):
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
@ -1015,23 +1015,21 @@ class Process(object):
def nice_set(self, value):
return cext.proc_priority_set(self.pid, value)
# available on Windows >= Vista
if HAS_PROC_IO_PRIORITY:
@wrap_exceptions
def ionice_get(self):
ret = cext.proc_io_priority_get(self.pid)
if enum is not None:
ret = IOPriority(ret)
return ret
@wrap_exceptions
def ionice_get(self):
ret = cext.proc_io_priority_get(self.pid)
if enum is not None:
ret = IOPriority(ret)
return ret
@wrap_exceptions
def ionice_set(self, ioclass, value):
if value:
raise TypeError("value argument not accepted on Windows")
if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL,
IOPRIO_HIGH):
raise ValueError("%s is not a valid priority" % ioclass)
cext.proc_io_priority_set(self.pid, ioclass)
@wrap_exceptions
def ionice_set(self, ioclass, value):
if value:
raise TypeError("value argument not accepted on Windows")
if ioclass not in (IOPRIO_VERYLOW, IOPRIO_LOW, IOPRIO_NORMAL,
IOPRIO_HIGH):
raise ValueError("%s is not a valid priority" % ioclass)
cext.proc_io_priority_set(self.pid, ioclass)
@wrap_exceptions
def io_counters(self):
@ -1040,7 +1038,7 @@ class Process(object):
except OSError as err:
if not is_permission_err(err):
raise
info = self.oneshot_info()
info = self._proc_info()
ret = (
info[pinfo_map['io_rcount']],
info[pinfo_map['io_wcount']],
@ -1097,11 +1095,11 @@ class Process(object):
return cext.proc_num_handles(self.pid)
except OSError as err:
if is_permission_err(err):
return self.oneshot_info()[pinfo_map['num_handles']]
return self._proc_info()[pinfo_map['num_handles']]
raise
@wrap_exceptions
def num_ctx_switches(self):
ctx_switches = self.oneshot_info()[pinfo_map['ctx_switches']]
ctx_switches = self._proc_info()[pinfo_map['ctx_switches']]
# only voluntary ctx switches are supported
return _common.pctxsw(ctx_switches, 0)

Просмотреть файл

@ -76,4 +76,4 @@ psutil_read_process_table(int * num) {
*num = np;
return processes;
}
}

Просмотреть файл

@ -146,4 +146,4 @@ error:
close(sd);
freeifaddrs(*ifap);
return (-1);
}
}

Просмотреть файл

@ -31,5 +31,4 @@ struct ifaddrs {
extern int getifaddrs(struct ifaddrs **);
extern void freeifaddrs(struct ifaddrs *);
#endif
#endif

Просмотреть файл

@ -12,4 +12,4 @@
PyObject* psutil_net_connections(PyObject *self, PyObject *args);
#endif /* __NET_CONNECTIONS_H__ */
#endif /* __NET_CONNECTIONS_H__ */

Просмотреть файл

@ -108,4 +108,4 @@ struct mbuf64
#define m_len m_hdr.mh_len
#endif /* __64BIT__ */
#endif /* __64BIT__ */

Просмотреть файл

@ -179,7 +179,7 @@ psutil_search_tcplist(char *buf, struct kinfo_file *kif) {
PyObject *
psutil_proc_connections(PyObject *self, PyObject *args) {
// Return connections opened by process.
long pid;
pid_t pid;
int i;
int cnt;
struct kinfo_file *freep = NULL;
@ -202,8 +202,11 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid,
&py_af_filter, &py_type_filter))
{
goto error;
}
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;

Просмотреть файл

@ -28,6 +28,7 @@
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
#define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * (uint32_t) \
(bt.frac >> 32) ) >> 32 ) / 1000000)
@ -43,7 +44,7 @@
int
psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc) {
psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
// Fills a kinfo_proc struct based on process pid.
int mib[4];
size_t size;
@ -60,7 +61,7 @@ psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc) {
// sysctl stores 0 in the size if we can't find the process information.
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
return -1;
}
return 0;
@ -87,81 +88,42 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
// this list. On success returns 0, else 1 with exception set.
int err;
struct kinfo_proc *result;
int done;
struct kinfo_proc *buf = NULL;
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 };
size_t length;
size_t length = 0;
assert( procList != NULL);
assert(procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);
*procCount = 0;
/*
* We start by calling sysctl with result == NULL and length == 0.
* That will succeed, and set length to the appropriate length.
* We then allocate a buffer of that size and call sysctl again
* with that buffer. If that succeeds, we're done. If that fails
* with ENOMEM, we have to throw away our buffer and loop. Note
* that the loop causes use to call sysctl with NULL again; this
* is necessary because the ENOMEM failure case sets length to
* the amount of data returned, not the amount of data that
* could have been returned.
*/
result = NULL;
done = 0;
do {
assert(result == NULL);
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length, NULL, 0);
if (err == -1)
err = errno;
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0) {
result = malloc(length);
if (result == NULL)
err = ENOMEM;
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length, NULL, 0);
if (err == -1)
err = errno;
if (err == 0) {
done = 1;
}
else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
// Call sysctl with a NULL buffer in order to get buffer length.
err = sysctl(name, 3, NULL, &length, NULL, 0);
if (err == -1) {
PyErr_SetFromOSErrnoWithSyscall("sysctl (null buffer)");
return 1;
}
*procList = result;
*procCount = length / sizeof(struct kinfo_proc);
// Allocate an appropriately sized buffer based on the results
// from the previous call.
buf = malloc(length);
if (buf == NULL) {
PyErr_NoMemory();
return 1;
}
assert((err == 0) == (*procList != NULL));
return err;
// Call sysctl again with the new buffer.
err = sysctl(name, 3, buf, &length, NULL, 0);
if (err == -1) {
PyErr_SetFromOSErrnoWithSyscall("sysctl");
free(buf);
return 1;
}
*procList = buf;
*procCount = length / sizeof(struct kinfo_proc);
return 0;
}
@ -179,7 +141,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
* 1 for insufficient privileges.
*/
static char
*psutil_get_cmd_args(long pid, size_t *argsize) {
*psutil_get_cmd_args(pid_t pid, size_t *argsize) {
int mib[4];
int argmax;
size_t size = sizeof(argmax);
@ -221,7 +183,7 @@ static char
// returns the command line as a python list object
PyObject *
psutil_get_cmdline(long pid) {
psutil_get_cmdline(pid_t pid) {
char *argstr = NULL;
size_t pos = 0;
size_t argsize = 0;
@ -268,14 +230,14 @@ error:
*/
PyObject *
psutil_proc_exe(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
char pathname[PATH_MAX];
int error;
int mib[4];
int ret;
size_t size;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
mib[0] = CTL_KERN;
@ -300,7 +262,7 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
if (ret == -1)
return NULL;
else if (ret == 0)
return NoSuchProcess("");
return NoSuchProcess("psutil_pid_exists");
else
strcpy(pathname, "");
}
@ -312,9 +274,9 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
PyObject *
psutil_proc_num_threads(PyObject *self, PyObject *args) {
// Return number of threads used by process as a Python integer.
long pid;
pid_t pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -329,7 +291,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
// Thanks to Robert N. M. Watson:
// http://code.metager.de/source/xref/freebsd/usr.bin/procstat/
// procstat_threads.c
long pid;
pid_t pid;
int mib[4];
struct kinfo_proc *kip = NULL;
struct kinfo_proc *kipp = NULL;
@ -341,7 +303,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
// we need to re-query for thread information, so don't use *kipp
@ -357,7 +319,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
goto error;
}
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
goto error;
}
@ -373,7 +335,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
goto error;
}
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
goto error;
}
@ -558,7 +520,7 @@ psutil_swap_mem(PyObject *self, PyObject *args) {
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
struct kinfo_file *freep = NULL;
struct kinfo_file *kif;
struct kinfo_proc kipp;
@ -566,7 +528,7 @@ psutil_proc_cwd(PyObject *self, PyObject *args) {
int i, cnt;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
if (psutil_kinfo_proc(pid, &kipp) == -1)
goto error;
@ -609,13 +571,13 @@ error:
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
PyObject *
psutil_proc_num_fds(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int cnt;
struct kinfo_file *freep;
struct kinfo_proc kipp;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kipp) == -1)
return NULL;
@ -767,8 +729,8 @@ error:
PyObject *
psutil_proc_memory_maps(PyObject *self, PyObject *args) {
// Return a list of tuples for every process memory maps.
//'procstat' cmdline utility has been used as an example.
long pid;
// 'procstat' cmdline utility has been used as an example.
pid_t pid;
int ptrwidth;
int i, cnt;
char addr[1000];
@ -784,7 +746,7 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
if (psutil_kinfo_proc(pid, &kp) == -1)
goto error;
@ -884,14 +846,14 @@ psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args) {
// Get process CPU affinity.
// Reference:
// http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
long pid;
pid_t pid;
int ret;
int i;
cpuset_t mask;
PyObject* py_retlist;
PyObject* py_cpu_num;
if (!PyArg_ParseTuple(args, "i", &pid))
if (!PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
sizeof(mask), &mask);
@ -926,7 +888,7 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
// Set process CPU affinity.
// Reference:
// http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
long pid;
pid_t pid;
int i;
int seq_len;
int ret;
@ -934,7 +896,7 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) {
PyObject *py_cpu_set;
PyObject *py_cpu_seq = NULL;
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &py_cpu_set))
return NULL;
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");

Просмотреть файл

@ -129,7 +129,7 @@ int psutil_gather_inet(int proto, PyObject *py_retlist) {
} while (xig->xig_gen != exig->xig_gen && retry--);
for (;;) {
struct xfile *xf;
struct xfile *xf;
int lport, rport, status, family;
xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
@ -203,19 +203,20 @@ int psutil_gather_inet(int proto, PyObject *py_retlist) {
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue(
"(iiiNNii)",
"iiiNNi" _Py_PARSE_PID,
xf->xf_fd, // fd
family, // family
type, // type
py_laddr, // laddr
py_raddr, // raddr
status, // status
xf->xf_pid); // pid
xf->xf_pid // pid
);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
Py_CLEAR(py_tuple);
}
free(buf);
@ -286,7 +287,7 @@ int psutil_gather_unix(int proto, PyObject *py_retlist) {
} while (xug->xug_gen != exug->xug_gen && retry--);
for (;;) {
struct xfile *xf;
struct xfile *xf;
xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len);
if (xug >= exug)

Просмотреть файл

@ -31,15 +31,16 @@
#include <sys/socket.h>
#include <sys/sched.h> // for CPUSTATES & CP_*
#define _KERNEL // for DTYPE_*
#include <sys/file.h>
#include <sys/file.h>
#undef _KERNEL
#include <sys/disk.h> // struct diskstats
#include <netinet/in.h>
#include <arpa/inet.h>
#include "specific.h"
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
#include "specific.h"
#define PSUTIL_KPT2DOUBLE(t) (t ## _sec + t ## _usec / 1000000.0)
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
@ -71,7 +72,7 @@ psutil_kinfo_proc(pid_t pid, kinfo_proc *proc) {
}
// sysctl stores 0 in the size if we can't find the process information.
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
return -1;
}
return 0;
@ -111,6 +112,47 @@ kinfo_getfile(pid_t pid, int* cnt) {
return kf;
}
PyObject *
psutil_proc_cwd(PyObject *self, PyObject *args) {
long pid;
char path[MAXPATHLEN];
size_t pathlen = sizeof path;
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
#ifdef KERN_PROC_CWD
int name[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD};
if (sysctl(name, 4, path, &pathlen, NULL, 0) != 0) {
if (errno == ENOENT)
NoSuchProcess("");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
#else
char *buf;
if (asprintf(&buf, "/proc/%d/cwd", (int)pid) < 0) {
PyErr_NoMemory();
return NULL;
}
ssize_t len = readlink(buf, path, sizeof(path) - 1);
free(buf);
if (len == -1) {
if (errno == ENOENT)
NoSuchProcess("readlink (ENOENT)");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
path[len] = '\0';
#endif
return PyUnicode_DecodeFSDefault(path);
}
// XXX: This is no longer used as per
// https://github.com/giampaolo/psutil/pull/557#issuecomment-171912820
@ -156,7 +198,7 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
if (ret == -1)
return NULL;
else if (ret == 0)
return NoSuchProcess("");
return NoSuchProcess("psutil_pid_exists");
else
strcpy(pathname, "");
}
@ -208,7 +250,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
goto error;
}
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
goto error;
}
@ -225,7 +267,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
goto error;
}
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
goto error;
}
@ -281,14 +323,14 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
if (kd == NULL) {
PyErr_Format(
PyExc_RuntimeError, "kvm_openfiles() syscall failed: %s", errbuf);
return errno;
return 1;
}
result = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(kinfo_proc), &cnt);
if (result == NULL) {
PyErr_Format(PyExc_RuntimeError, "kvm_getproc2() syscall failed");
kvm_close(kd);
return errno;
return 1;
}
*procCount = (size_t)cnt;
@ -298,7 +340,7 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) {
if ((*procList = malloc(mlen)) == NULL) {
PyErr_NoMemory();
kvm_close(kd);
return errno;
return 1;
}
memcpy(*procList, result, mlen);

Просмотреть файл

@ -26,3 +26,4 @@ PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
PyObject *psutil_proc_cwd(PyObject *self, PyObject *args);

Просмотреть файл

@ -46,6 +46,21 @@
// Utility functions
// ============================================================================
static void
convert_kvm_err(const char *syscall, char *errbuf) {
char fullmsg[8192];
sprintf(fullmsg, "(originated from %s: %s)", syscall, errbuf);
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied(fullmsg);
else if (strstr(errbuf, "Operation not permitted") != NULL)
AccessDenied(fullmsg);
else
PyErr_Format(PyExc_RuntimeError, fullmsg);
}
int
psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
// Fills a kinfo_proc struct based on process pid.
@ -67,7 +82,7 @@ psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
}
// sysctl stores 0 in the size if we can't find the process information.
if (size == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (size = 0)");
return -1;
}
return 0;
@ -75,7 +90,7 @@ psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {
struct kinfo_file *
kinfo_getfile(long pid, int* cnt) {
kinfo_getfile(pid_t pid, int* cnt) {
// Mimic's FreeBSD kinfo_file call, taking a pid and a ptr to an
// int as arg and returns an array with cnt struct kinfo_file.
int mib[6];
@ -84,7 +99,7 @@ kinfo_getfile(long pid, int* cnt) {
mib[0] = CTL_KERN;
mib[1] = KERN_FILE;
mib[2] = KERN_FILE_BYPID;
mib[3] = (int) pid;
mib[3] = pid;
mib[4] = sizeof(struct kinfo_file);
mib[5] = 0;
@ -133,16 +148,16 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
assert(procCount != NULL);
kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
if (kd == NULL) {
return errno;
if (! kd) {
convert_kvm_err("kvm_openfiles", errbuf);
return 1;
}
result = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &cnt);
if (result == NULL) {
PyErr_Format(PyExc_RuntimeError, "kvm_getprocs syscall failed");
kvm_close(kd);
err(1, NULL);
return errno;
return 1;
}
*procCount = (size_t)cnt;
@ -150,9 +165,9 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
size_t mlen = cnt * sizeof(struct kinfo_proc);
if ((*procList = malloc(mlen)) == NULL) {
PyErr_NoMemory();
kvm_close(kd);
err(1, NULL);
return errno;
return 1;
}
memcpy(*procList, result, mlen);
@ -163,8 +178,8 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) {
}
char **
_psutil_get_argv(long pid) {
static char **
_psutil_get_argv(pid_t pid) {
static char **argv;
int argv_mib[] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
size_t argv_size = 128;
@ -189,7 +204,7 @@ _psutil_get_argv(long pid) {
// returns the command line as a python list object
PyObject *
psutil_get_cmdline(long pid) {
psutil_get_cmdline(pid_t pid) {
static char **argv;
char **p;
PyObject *py_arg = NULL;
@ -226,7 +241,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
// https://github.com/janmojzis/pstree/blob/master/proc_kvm.c
// Note: this requires root access, else it will fail trying
// to access /dev/kmem.
long pid;
pid_t pid;
kvm_t *kd = NULL;
int nentries, i;
char errbuf[4096];
@ -236,15 +251,12 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
goto error;
kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf);
if (! kd) {
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied("");
else
PyErr_Format(PyExc_RuntimeError, "kvm_openfiles() syscall failed");
convert_kvm_err("kvm_openfiles()", errbuf);
goto error;
}
@ -253,7 +265,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
sizeof(*kp), &nentries);
if (! kp) {
if (strstr(errbuf, "Permission denied") != NULL)
AccessDenied("");
AccessDenied("kvm_getprocs");
else
PyErr_Format(PyExc_RuntimeError, "kvm_getprocs() syscall failed");
goto error;
@ -264,7 +276,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) {
continue;
if (kp[i].p_pid == pid) {
py_tuple = Py_BuildValue(
"Idd",
_Py_PARSE_PID "dd",
kp[i].p_tid,
PSUTIL_KPT2DOUBLE(kp[i].p_uutime),
PSUTIL_KPT2DOUBLE(kp[i].p_ustime));
@ -390,25 +402,23 @@ error:
PyObject *
psutil_proc_num_fds(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int cnt;
struct kinfo_file *freep;
struct kinfo_proc kipp;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kipp) == -1)
return NULL;
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
if (freep == NULL)
return NULL;
}
free(freep);
free(freep);
return Py_BuildValue("i", cnt);
}
@ -418,12 +428,12 @@ psutil_proc_cwd(PyObject *self, PyObject *args) {
// Reference:
// https://github.com/openbsd/src/blob/
// 588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L191
long pid;
pid_t pid;
struct kinfo_proc kp;
char path[MAXPATHLEN];
size_t pathlen = sizeof path;
if (! PyArg_ParseTuple(args, "l", &pid))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
@ -482,7 +492,7 @@ psutil_inet6_addrstr(struct in6_addr *p)
*/
PyObject *
psutil_proc_connections(PyObject *self, PyObject *args) {
long pid;
pid_t pid;
int i;
int cnt;
struct kinfo_file *freep = NULL;
@ -499,17 +509,16 @@ psutil_proc_connections(PyObject *self, PyObject *args) {
if (py_retlist == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &py_af_filter, &py_type_filter))
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "OO", &pid, &py_af_filter,
&py_type_filter))
goto error;
if (!PySequence_Check(py_af_filter) || !PySequence_Check(py_type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
}
errno = 0;
freep = kinfo_getfile(pid, &cnt);
if (freep == NULL) {
psutil_raise_for_pid(pid, "kinfo_getfile()");
goto error;
}

Просмотреть файл

@ -10,10 +10,10 @@
typedef struct kinfo_proc kinfo_proc;
int psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc);
struct kinfo_file * kinfo_getfile(long pid, int* cnt);
struct kinfo_file * kinfo_getfile(pid_t pid, int* cnt);
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
char **_psutil_get_argv(long pid);
PyObject * psutil_get_cmdline(long pid);
char **_psutil_get_argv(pid_t pid);
PyObject * psutil_get_cmdline(pid_t pid);
//
PyObject *psutil_proc_threads(PyObject *self, PyObject *args);

Просмотреть файл

@ -19,9 +19,9 @@
#include <sys/sysctl.h>
#include <libproc.h>
#include "process_info.h"
#include "../../_psutil_common.h"
#include "../../_psutil_posix.h"
#include "process_info.h"
/*
* Returns a list of all BSD processes on the system. This routine
@ -119,7 +119,7 @@ psutil_get_argmax() {
// Return 1 if pid refers to a zombie process else 0.
int
psutil_is_zombie(long pid) {
psutil_is_zombie(pid_t pid) {
struct kinfo_proc kp;
if (psutil_get_kinfo_proc(pid, &kp) == -1)
@ -131,7 +131,7 @@ psutil_is_zombie(long pid) {
// return process args as a python list
PyObject *
psutil_get_cmdline(long pid) {
psutil_get_cmdline(pid_t pid) {
int mib[3];
int nargs;
size_t len;
@ -162,12 +162,12 @@ psutil_get_cmdline(long pid) {
// read argument space
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = (pid_t)pid;
mib[2] = pid;
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
// In case of zombie process we'll get EINVAL. We translate it
// to NSP and _psosx.py will translate it to ZP.
if ((errno == EINVAL) && (psutil_pid_exists(pid)))
NoSuchProcess("");
NoSuchProcess("sysctl");
else
PyErr_SetFromErrno(PyExc_OSError);
goto error;
@ -225,7 +225,7 @@ error:
// return process environment as a python string
PyObject *
psutil_get_environ(long pid) {
psutil_get_environ(pid_t pid) {
int mib[3];
int nargs;
char *procargs = NULL;
@ -254,12 +254,12 @@ psutil_get_environ(long pid) {
// read argument space
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = (pid_t)pid;
mib[2] = pid;
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
// In case of zombie process we'll get EINVAL. We translate it
// to NSP and _psosx.py will translate it to ZP.
if ((errno == EINVAL) && (psutil_pid_exists(pid)))
NoSuchProcess("");
NoSuchProcess("sysctl");
else
PyErr_SetFromErrno(PyExc_OSError);
goto error;
@ -339,13 +339,13 @@ error:
int
psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) {
int mib[4];
size_t len;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = (pid_t)pid;
mib[3] = pid;
// fetch the info with sysctl()
len = sizeof(struct kinfo_proc);
@ -359,7 +359,7 @@ psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
// sysctl succeeds but len is zero, happens when process has gone away
if (len == 0) {
NoSuchProcess("");
NoSuchProcess("sysctl (len == 0)");
return -1;
}
return 0;
@ -371,9 +371,9 @@ psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp) {
* Returns 0 on failure (and Python exception gets already set).
*/
int
psutil_proc_pidinfo(long pid, int flavor, uint64_t arg, void *pti, int size) {
psutil_proc_pidinfo(pid_t pid, int flavor, uint64_t arg, void *pti, int size) {
errno = 0;
int ret = proc_pidinfo((int)pid, flavor, arg, pti, size);
int ret = proc_pidinfo(pid, flavor, arg, pti, size);
if ((ret <= 0) || ((unsigned long)ret < sizeof(pti))) {
psutil_raise_for_pid(pid, "proc_pidinfo()");
return 0;

Просмотреть файл

@ -9,10 +9,10 @@
typedef struct kinfo_proc kinfo_proc;
int psutil_get_argmax(void);
int psutil_is_zombie(long pid);
int psutil_get_kinfo_proc(long pid, struct kinfo_proc *kp);
int psutil_is_zombie(pid_t pid);
int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
int psutil_proc_pidinfo(
long pid, int flavor, uint64_t arg, void *pti, int size);
PyObject* psutil_get_cmdline(long pid);
PyObject* psutil_get_environ(long pid);
pid_t pid, int flavor, uint64_t arg, void *pti, int size);
PyObject* psutil_get_cmdline(pid_t pid);
PyObject* psutil_get_environ(pid_t pid);

Просмотреть файл

@ -6,14 +6,13 @@
* Functions specific for Process.environ().
*/
#define NEW_MIB_COMPLIANT 1
#define _STRUCTURED_PROC 1
#include <Python.h>
#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
# undef _FILE_OFFSET_BITS
# undef _LARGEFILE64_SOURCE
#undef _FILE_OFFSET_BITS
#undef _LARGEFILE64_SOURCE
#endif
#include <sys/types.h>

415
third_party/python/psutil/psutil/arch/windows/cpu.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,415 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include <windows.h>
#include <PowrProf.h>
#include "../../_psutil_common.h"
/*
* Return the number of logical, active CPUs. Return 0 if undetermined.
* See discussion at: https://bugs.python.org/issue33166#msg314631
*/
static unsigned int
psutil_get_num_cpus(int fail_on_err) {
unsigned int ncpus = 0;
// Minimum requirement: Windows 7
if (GetActiveProcessorCount != NULL) {
ncpus = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
if ((ncpus == 0) && (fail_on_err == 1)) {
PyErr_SetFromWindowsErr(0);
}
}
else {
psutil_debug("GetActiveProcessorCount() not available; "
"using GetSystemInfo()");
ncpus = (unsigned int)PSUTIL_SYSTEM_INFO.dwNumberOfProcessors;
if ((ncpus <= 0) && (fail_on_err == 1)) {
PyErr_SetString(
PyExc_RuntimeError,
"GetSystemInfo() failed to retrieve CPU count");
}
}
return ncpus;
}
/*
* Retrieves system CPU timing information as a (user, system, idle)
* tuple. On a multiprocessor system, the values returned are the
* sum of the designated times across all processors.
*/
PyObject *
psutil_cpu_times(PyObject *self, PyObject *args) {
double idle, kernel, user, system;
FILETIME idle_time, kernel_time, user_time;
if (!GetSystemTimes(&idle_time, &kernel_time, &user_time)) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
idle = (double)((HI_T * idle_time.dwHighDateTime) + \
(LO_T * idle_time.dwLowDateTime));
user = (double)((HI_T * user_time.dwHighDateTime) + \
(LO_T * user_time.dwLowDateTime));
kernel = (double)((HI_T * kernel_time.dwHighDateTime) + \
(LO_T * kernel_time.dwLowDateTime));
// Kernel time includes idle time.
// We return only busy kernel time subtracting idle time from
// kernel time.
system = (kernel - idle);
return Py_BuildValue("(ddd)", user, system, idle);
}
/*
* Same as above but for all system CPUs.
*/
PyObject *
psutil_per_cpu_times(PyObject *self, PyObject *args) {
double idle, kernel, systemt, user, interrupt, dpc;
NTSTATUS status;
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
UINT i;
unsigned int ncpus;
PyObject *py_tuple = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
// retrieves number of processors
ncpus = psutil_get_num_cpus(1);
if (ncpus == 0)
goto error;
// allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
// structures, one per processor
sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if (sppi == NULL) {
PyErr_NoMemory();
goto error;
}
// gets cpu time informations
status = NtQuerySystemInformation(
SystemProcessorPerformanceInformation,
sppi,
ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
NULL);
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status,
"NtQuerySystemInformation(SystemProcessorPerformanceInformation)"
);
goto error;
}
// computes system global times summing each
// processor value
idle = user = kernel = interrupt = dpc = 0;
for (i = 0; i < ncpus; i++) {
py_tuple = NULL;
user = (double)((HI_T * sppi[i].UserTime.HighPart) +
(LO_T * sppi[i].UserTime.LowPart));
idle = (double)((HI_T * sppi[i].IdleTime.HighPart) +
(LO_T * sppi[i].IdleTime.LowPart));
kernel = (double)((HI_T * sppi[i].KernelTime.HighPart) +
(LO_T * sppi[i].KernelTime.LowPart));
interrupt = (double)((HI_T * sppi[i].InterruptTime.HighPart) +
(LO_T * sppi[i].InterruptTime.LowPart));
dpc = (double)((HI_T * sppi[i].DpcTime.HighPart) +
(LO_T * sppi[i].DpcTime.LowPart));
// kernel time includes idle time on windows
// we return only busy kernel time subtracting
// idle time from kernel time
systemt = kernel - idle;
py_tuple = Py_BuildValue(
"(ddddd)",
user,
systemt,
idle,
interrupt,
dpc
);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_CLEAR(py_tuple);
}
free(sppi);
return py_retlist;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
if (sppi)
free(sppi);
return NULL;
}
/*
* Return the number of active, logical CPUs.
*/
PyObject *
psutil_cpu_count_logical(PyObject *self, PyObject *args) {
unsigned int ncpus;
ncpus = psutil_get_num_cpus(0);
if (ncpus != 0)
return Py_BuildValue("I", ncpus);
else
Py_RETURN_NONE; // mimick os.cpu_count()
}
/*
* Return the number of physical CPU cores (hyper-thread CPUs count
* is excluded).
*/
PyObject *
psutil_cpu_count_phys(PyObject *self, PyObject *args) {
DWORD rc;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL;
DWORD length = 0;
DWORD offset = 0;
DWORD ncpus = 0;
DWORD prev_processor_info_size = 0;
// GetLogicalProcessorInformationEx() is available from Windows 7
// onward. Differently from GetLogicalProcessorInformation()
// it supports process groups, meaning this is able to report more
// than 64 CPUs. See:
// https://bugs.python.org/issue33166
if (GetLogicalProcessorInformationEx == NULL) {
psutil_debug("Win < 7; cpu_count_phys() forced to None");
Py_RETURN_NONE;
}
while (1) {
rc = GetLogicalProcessorInformationEx(
RelationAll, buffer, &length);
if (rc == FALSE) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (buffer) {
free(buffer);
}
buffer = \
(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length);
if (NULL == buffer) {
PyErr_NoMemory();
return NULL;
}
}
else {
psutil_debug("GetLogicalProcessorInformationEx() returned ",
GetLastError());
goto return_none;
}
}
else {
break;
}
}
ptr = buffer;
while (offset < length) {
// Advance ptr by the size of the previous
// SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX struct.
ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*) \
(((char*)ptr) + prev_processor_info_size);
if (ptr->Relationship == RelationProcessorCore) {
ncpus += 1;
}
// When offset == length, we've reached the last processor
// info struct in the buffer.
offset += ptr->Size;
prev_processor_info_size = ptr->Size;
}
free(buffer);
if (ncpus != 0) {
return Py_BuildValue("I", ncpus);
}
else {
psutil_debug("GetLogicalProcessorInformationEx() count was 0");
Py_RETURN_NONE; // mimick os.cpu_count()
}
return_none:
if (buffer != NULL)
free(buffer);
Py_RETURN_NONE;
}
/*
* Return CPU statistics.
*/
PyObject *
psutil_cpu_stats(PyObject *self, PyObject *args) {
NTSTATUS status;
_SYSTEM_PERFORMANCE_INFORMATION *spi = NULL;
_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
_SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL;
unsigned int ncpus;
UINT i;
ULONG64 dpcs = 0;
ULONG interrupts = 0;
// retrieves number of processors
ncpus = psutil_get_num_cpus(1);
if (ncpus == 0)
goto error;
// get syscalls / ctx switches
spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \
malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION));
if (spi == NULL) {
PyErr_NoMemory();
goto error;
}
status = NtQuerySystemInformation(
SystemPerformanceInformation,
spi,
ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION),
NULL);
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status, "NtQuerySystemInformation(SystemPerformanceInformation)");
goto error;
}
// get DPCs
InterruptInformation = \
malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus);
if (InterruptInformation == NULL) {
PyErr_NoMemory();
goto error;
}
status = NtQuerySystemInformation(
SystemInterruptInformation,
InterruptInformation,
ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION),
NULL);
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status, "NtQuerySystemInformation(SystemInterruptInformation)");
goto error;
}
for (i = 0; i < ncpus; i++) {
dpcs += InterruptInformation[i].DpcCount;
}
// get interrupts
sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \
malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
if (sppi == NULL) {
PyErr_NoMemory();
goto error;
}
status = NtQuerySystemInformation(
SystemProcessorPerformanceInformation,
sppi,
ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION),
NULL);
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status,
"NtQuerySystemInformation(SystemProcessorPerformanceInformation)");
goto error;
}
for (i = 0; i < ncpus; i++) {
interrupts += sppi[i].InterruptCount;
}
// done
free(spi);
free(InterruptInformation);
free(sppi);
return Py_BuildValue(
"kkkk",
spi->ContextSwitches,
interrupts,
(unsigned long)dpcs,
spi->SystemCalls
);
error:
if (spi)
free(spi);
if (InterruptInformation)
free(InterruptInformation);
if (sppi)
free(sppi);
return NULL;
}
/*
* Return CPU frequency.
*/
PyObject *
psutil_cpu_freq(PyObject *self, PyObject *args) {
PROCESSOR_POWER_INFORMATION *ppi;
NTSTATUS ret;
ULONG size;
LPBYTE pBuffer = NULL;
ULONG current;
ULONG max;
unsigned int ncpus;
// Get the number of CPUs.
ncpus = psutil_get_num_cpus(1);
if (ncpus == 0)
return NULL;
// Allocate size.
size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION);
pBuffer = (BYTE*)LocalAlloc(LPTR, size);
if (! pBuffer) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
// Syscall.
ret = CallNtPowerInformation(
ProcessorInformation, NULL, 0, pBuffer, size);
if (ret != 0) {
PyErr_SetString(PyExc_RuntimeError,
"CallNtPowerInformation syscall failed");
goto error;
}
// Results.
ppi = (PROCESSOR_POWER_INFORMATION *)pBuffer;
max = ppi->MaxMhz;
current = ppi->CurrentMhz;
LocalFree(pBuffer);
return Py_BuildValue("kk", current, max);
error:
if (pBuffer != NULL)
LocalFree(pBuffer);
return NULL;
}

14
third_party/python/psutil/psutil/arch/windows/cpu.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,14 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
PyObject *psutil_cpu_count_logical(PyObject *self, PyObject *args);
PyObject *psutil_cpu_count_phys(PyObject *self, PyObject *args);
PyObject *psutil_cpu_freq(PyObject *self, PyObject *args);
PyObject *psutil_cpu_stats(PyObject *self, PyObject *args);
PyObject *psutil_cpu_times(PyObject *self, PyObject *args);
PyObject *psutil_per_cpu_times(PyObject *self, PyObject *args);

373
third_party/python/psutil/psutil/arch/windows/disk.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,373 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include <windows.h>
#include <tchar.h>
#include "../../_psutil_common.h"
#ifndef _ARRAYSIZE
#define _ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
static char *psutil_get_drive_type(int type) {
switch (type) {
case DRIVE_FIXED:
return "fixed";
case DRIVE_CDROM:
return "cdrom";
case DRIVE_REMOVABLE:
return "removable";
case DRIVE_UNKNOWN:
return "unknown";
case DRIVE_NO_ROOT_DIR:
return "unmounted";
case DRIVE_REMOTE:
return "remote";
case DRIVE_RAMDISK:
return "ramdisk";
default:
return "?";
}
}
/*
* Return path's disk total and free as a Python tuple.
*/
PyObject *
psutil_disk_usage(PyObject *self, PyObject *args) {
BOOL retval;
ULARGE_INTEGER _, total, free;
char *path;
if (PyArg_ParseTuple(args, "u", &path)) {
Py_BEGIN_ALLOW_THREADS
retval = GetDiskFreeSpaceExW((LPCWSTR)path, &_, &total, &free);
Py_END_ALLOW_THREADS
goto return_;
}
// on Python 2 we also want to accept plain strings other
// than Unicode
#if PY_MAJOR_VERSION <= 2
PyErr_Clear(); // drop the argument parsing error
if (PyArg_ParseTuple(args, "s", &path)) {
Py_BEGIN_ALLOW_THREADS
retval = GetDiskFreeSpaceEx(path, &_, &total, &free);
Py_END_ALLOW_THREADS
goto return_;
}
#endif
return NULL;
return_:
if (retval == 0)
return PyErr_SetFromWindowsErrWithFilename(0, path);
else
return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart);
}
/*
* Return a Python dict of tuples for disk I/O information. This may
* require running "diskperf -y" command first.
*/
PyObject *
psutil_disk_io_counters(PyObject *self, PyObject *args) {
DISK_PERFORMANCE diskPerformance;
DWORD dwSize;
HANDLE hDevice = NULL;
char szDevice[MAX_PATH];
char szDeviceDisplay[MAX_PATH];
int devNum;
int i;
DWORD ioctrlSize;
BOOL ret;
PyObject *py_retdict = PyDict_New();
PyObject *py_tuple = NULL;
if (py_retdict == NULL)
return NULL;
// Apparently there's no way to figure out how many times we have
// to iterate in order to find valid drives.
// Let's assume 32, which is higher than 26, the number of letters
// in the alphabet (from A:\ to Z:\).
for (devNum = 0; devNum <= 32; ++devNum) {
py_tuple = NULL;
sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum);
hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
continue;
// DeviceIoControl() sucks!
i = 0;
ioctrlSize = sizeof(diskPerformance);
while (1) {
i += 1;
ret = DeviceIoControl(
hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &diskPerformance,
ioctrlSize, &dwSize, NULL);
if (ret != 0)
break; // OK!
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Retry with a bigger buffer (+ limit for retries).
if (i <= 1024) {
ioctrlSize *= 2;
continue;
}
}
else if (GetLastError() == ERROR_INVALID_FUNCTION) {
// This happens on AppVeyor:
// https://ci.appveyor.com/project/giampaolo/psutil/build/
// 1364/job/ascpdi271b06jle3
// Assume it means we're dealing with some exotic disk
// and go on.
psutil_debug("DeviceIoControl -> ERROR_INVALID_FUNCTION; "
"ignore PhysicalDrive%i", devNum);
goto next;
}
else if (GetLastError() == ERROR_NOT_SUPPORTED) {
// Again, let's assume we're dealing with some exotic disk.
psutil_debug("DeviceIoControl -> ERROR_NOT_SUPPORTED; "
"ignore PhysicalDrive%i", devNum);
goto next;
}
// XXX: it seems we should also catch ERROR_INVALID_PARAMETER:
// https://sites.ualberta.ca/dept/aict/uts/software/openbsd/
// ports/4.1/i386/openafs/w-openafs-1.4.14-transarc/
// openafs-1.4.14/src/usd/usd_nt.c
// XXX: we can also bump into ERROR_MORE_DATA in which case
// (quoting doc) we're supposed to retry with a bigger buffer
// and specify a new "starting point", whatever it means.
PyErr_SetFromWindowsErr(0);
goto error;
}
sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%i", devNum);
py_tuple = Py_BuildValue(
"(IILLKK)",
diskPerformance.ReadCount,
diskPerformance.WriteCount,
diskPerformance.BytesRead,
diskPerformance.BytesWritten,
// convert to ms:
// https://github.com/giampaolo/psutil/issues/1012
(unsigned long long)
(diskPerformance.ReadTime.QuadPart) / 10000000,
(unsigned long long)
(diskPerformance.WriteTime.QuadPart) / 10000000);
if (!py_tuple)
goto error;
if (PyDict_SetItemString(py_retdict, szDeviceDisplay, py_tuple))
goto error;
Py_CLEAR(py_tuple);
next:
CloseHandle(hDevice);
}
return py_retdict;
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retdict);
if (hDevice != NULL)
CloseHandle(hDevice);
return NULL;
}
/*
* Return disk partitions as a list of tuples such as
* (drive_letter, drive_letter, type, "")
*/
PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args) {
DWORD num_bytes;
char drive_strings[255];
char *drive_letter = drive_strings;
char mp_buf[MAX_PATH];
char mp_path[MAX_PATH];
int all;
int type;
int ret;
unsigned int old_mode = 0;
char opts[20];
HANDLE mp_h;
BOOL mp_flag= TRUE;
LPTSTR fs_type[MAX_PATH + 1] = { 0 };
DWORD pflags = 0;
PyObject *py_all;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL) {
return NULL;
}
// avoid to visualize a message box in case something goes wrong
// see https://github.com/giampaolo/psutil/issues/264
old_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
if (! PyArg_ParseTuple(args, "O", &py_all))
goto error;
all = PyObject_IsTrue(py_all);
Py_BEGIN_ALLOW_THREADS
num_bytes = GetLogicalDriveStrings(254, drive_letter);
Py_END_ALLOW_THREADS
if (num_bytes == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}
while (*drive_letter != 0) {
py_tuple = NULL;
opts[0] = 0;
fs_type[0] = 0;
Py_BEGIN_ALLOW_THREADS
type = GetDriveType(drive_letter);
Py_END_ALLOW_THREADS
// by default we only show hard drives and cd-roms
if (all == 0) {
if ((type == DRIVE_UNKNOWN) ||
(type == DRIVE_NO_ROOT_DIR) ||
(type == DRIVE_REMOTE) ||
(type == DRIVE_RAMDISK)) {
goto next;
}
// floppy disk: skip it by default as it introduces a
// considerable slowdown.
if ((type == DRIVE_REMOVABLE) &&
(strcmp(drive_letter, "A:\\") == 0)) {
goto next;
}
}
ret = GetVolumeInformation(
(LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter),
NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type));
if (ret == 0) {
// We might get here in case of a floppy hard drive, in
// which case the error is (21, "device not ready").
// Let's pretend it didn't happen as we already have
// the drive name and type ('removable').
strcat_s(opts, _countof(opts), "");
SetLastError(0);
}
else {
if (pflags & FILE_READ_ONLY_VOLUME)
strcat_s(opts, _countof(opts), "ro");
else
strcat_s(opts, _countof(opts), "rw");
if (pflags & FILE_VOLUME_IS_COMPRESSED)
strcat_s(opts, _countof(opts), ",compressed");
// Check for mount points on this volume and add/get info
// (checks first to know if we can even have mount points)
if (pflags & FILE_SUPPORTS_REPARSE_POINTS) {
mp_h = FindFirstVolumeMountPoint(
drive_letter, mp_buf, MAX_PATH);
if (mp_h != INVALID_HANDLE_VALUE) {
while (mp_flag) {
// Append full mount path with drive letter
strcpy_s(mp_path, _countof(mp_path), drive_letter);
strcat_s(mp_path, _countof(mp_path), mp_buf);
py_tuple = Py_BuildValue(
"(ssss)",
drive_letter,
mp_path,
fs_type, // Typically NTFS
opts);
if (!py_tuple ||
PyList_Append(py_retlist, py_tuple) == -1) {
FindVolumeMountPointClose(mp_h);
goto error;
}
Py_CLEAR(py_tuple);
// Continue looking for more mount points
mp_flag = FindNextVolumeMountPoint(
mp_h, mp_buf, MAX_PATH);
}
FindVolumeMountPointClose(mp_h);
}
}
}
if (strlen(opts) > 0)
strcat_s(opts, _countof(opts), ",");
strcat_s(opts, _countof(opts), psutil_get_drive_type(type));
py_tuple = Py_BuildValue(
"(ssss)",
drive_letter,
drive_letter,
fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS
opts);
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_CLEAR(py_tuple);
goto next;
next:
drive_letter = strchr(drive_letter, 0) + 1;
}
SetErrorMode(old_mode);
return py_retlist;
error:
SetErrorMode(old_mode);
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
return NULL;
}
/*
Accept a filename's drive in native format like "\Device\HarddiskVolume1\"
and return the corresponding drive letter (e.g. "C:\\").
If no match is found return an empty string.
*/
PyObject *
psutil_win32_QueryDosDevice(PyObject *self, PyObject *args) {
LPCTSTR lpDevicePath;
TCHAR d = TEXT('A');
TCHAR szBuff[5];
if (!PyArg_ParseTuple(args, "s", &lpDevicePath))
return NULL;
while (d <= TEXT('Z')) {
TCHAR szDeviceName[3] = {d, TEXT(':'), TEXT('\0')};
TCHAR szTarget[512] = {0};
if (QueryDosDevice(szDeviceName, szTarget, 511) != 0) {
if (_tcscmp(lpDevicePath, szTarget) == 0) {
_stprintf_s(szBuff, _countof(szBuff), TEXT("%c:"), d);
return Py_BuildValue("s", szBuff);
}
}
d++;
}
return Py_BuildValue("s", "");
}

12
third_party/python/psutil/psutil/arch/windows/disk.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
PyObject *psutil_disk_io_counters(PyObject *self, PyObject *args);
PyObject *psutil_disk_partitions(PyObject *self, PyObject *args);
PyObject *psutil_disk_usage(PyObject *self, PyObject *args);
PyObject *psutil_win32_QueryDosDevice(PyObject *self, PyObject *args);

Просмотреть файл

@ -1,234 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* This code is executed on import. It loads private/undocumented
* Windows APIs and sets Windows version constants so that they are
* available globally.
*/
#include <windows.h>
#include <Python.h>
#include "ntextapi.h"
#include "global.h"
// Needed to make these globally visible.
int PSUTIL_WINVER;
SYSTEM_INFO PSUTIL_SYSTEM_INFO;
#define NT_FACILITY_MASK 0xfff
#define NT_FACILITY_SHIFT 16
#define NT_FACILITY(Status) \
((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK)
#define NT_NTWIN32(status) (NT_FACILITY(Status) == FACILITY_WIN32)
#define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff)
// A wrapper around GetModuleHandle and GetProcAddress.
PVOID
psutil_GetProcAddress(LPCSTR libname, LPCSTR procname) {
HMODULE mod;
FARPROC addr;
if ((mod = GetModuleHandleA(libname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, libname);
return NULL;
}
if ((addr = GetProcAddress(mod, procname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, procname);
return NULL;
}
return addr;
}
// A wrapper around LoadLibrary and GetProcAddress.
PVOID
psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname) {
HMODULE mod;
FARPROC addr;
Py_BEGIN_ALLOW_THREADS
mod = LoadLibraryA(libname);
Py_END_ALLOW_THREADS
if (mod == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, libname);
return NULL;
}
if ((addr = GetProcAddress(mod, procname)) == NULL) {
PyErr_SetFromWindowsErrWithFilename(0, procname);
FreeLibrary(mod);
return NULL;
}
// Causes crash.
// FreeLibrary(mod);
return addr;
}
/*
* Convert a NTSTATUS value to a Win32 error code and set the proper
* Python exception.
*/
PVOID
psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall) {
ULONG err;
char fullmsg[1024];
if (NT_NTWIN32(Status))
err = WIN32_FROM_NTSTATUS(Status);
else
err = psutil_RtlNtStatusToDosErrorNoTeb(Status);
// if (GetLastError() != 0)
// err = GetLastError();
sprintf(fullmsg, "(originated from %s)", syscall);
return PyErr_SetFromWindowsErrWithFilename(err, fullmsg);
}
static int
psutil_loadlibs() {
/*
* Mandatory.
*/
psutil_NtQuerySystemInformation = psutil_GetProcAddressFromLib(
"ntdll.dll", "NtQuerySystemInformation");
if (psutil_NtQuerySystemInformation == NULL)
return 1;
psutil_NtQueryInformationProcess = psutil_GetProcAddress(
"ntdll.dll", "NtQueryInformationProcess");
if (! psutil_NtQueryInformationProcess)
return 1;
psutil_NtSetInformationProcess = psutil_GetProcAddress(
"ntdll.dll", "NtSetInformationProcess");
if (! psutil_NtSetInformationProcess)
return 1;
psutil_WinStationQueryInformationW = psutil_GetProcAddressFromLib(
"winsta.dll", "WinStationQueryInformationW");
if (! psutil_WinStationQueryInformationW)
return 1;
psutil_NtQueryObject = psutil_GetProcAddressFromLib(
"ntdll.dll", "NtQueryObject");
if (! psutil_NtQueryObject)
return 1;
psutil_rtlIpv4AddressToStringA = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlIpv4AddressToStringA");
if (! psutil_rtlIpv4AddressToStringA)
return 1;
// minimum requirement: Win XP SP3
psutil_GetExtendedTcpTable = psutil_GetProcAddressFromLib(
"iphlpapi.dll", "GetExtendedTcpTable");
if (! psutil_GetExtendedTcpTable)
return 1;
// minimum requirement: Win XP SP3
psutil_GetExtendedUdpTable = psutil_GetProcAddressFromLib(
"iphlpapi.dll", "GetExtendedUdpTable");
if (! psutil_GetExtendedUdpTable)
return 1;
psutil_RtlGetVersion = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlGetVersion");
if (! psutil_RtlGetVersion)
return 1;
psutil_NtSuspendProcess = psutil_GetProcAddressFromLib(
"ntdll", "NtSuspendProcess");
if (! psutil_NtSuspendProcess)
return 1;
psutil_NtResumeProcess = psutil_GetProcAddressFromLib(
"ntdll", "NtResumeProcess");
if (! psutil_NtResumeProcess)
return 1;
psutil_NtQueryVirtualMemory = psutil_GetProcAddressFromLib(
"ntdll", "NtQueryVirtualMemory");
if (! psutil_NtQueryVirtualMemory)
return 1;
psutil_RtlNtStatusToDosErrorNoTeb = psutil_GetProcAddressFromLib(
"ntdll", "RtlNtStatusToDosErrorNoTeb");
if (! psutil_RtlNtStatusToDosErrorNoTeb)
return 1;
/*
* Optional.
*/
// not available on Wine
psutil_rtlIpv6AddressToStringA = psutil_GetProcAddressFromLib(
"ntdll.dll", "RtlIpv6AddressToStringA");
// minimum requirement: Win Vista
psutil_GetTickCount64 = psutil_GetProcAddress(
"kernel32", "GetTickCount64");
// minimum requirement: Win 7
psutil_GetActiveProcessorCount = psutil_GetProcAddress(
"kernel32", "GetActiveProcessorCount");
// minumum requirement: Win 7
psutil_GetLogicalProcessorInformationEx = psutil_GetProcAddressFromLib(
"kernel32", "GetLogicalProcessorInformationEx");
PyErr_Clear();
return 0;
}
static int
psutil_set_winver() {
RTL_OSVERSIONINFOEXW versionInfo;
ULONG maj;
ULONG min;
versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
memset(&versionInfo, 0, sizeof(RTL_OSVERSIONINFOEXW));
psutil_RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo);
maj = versionInfo.dwMajorVersion;
min = versionInfo.dwMinorVersion;
if (maj == 5 && min == 1)
PSUTIL_WINVER = PSUTIL_WINDOWS_XP;
else if (maj == 5 && min == 2)
PSUTIL_WINVER = PSUTIL_WINDOWS_SERVER_2003;
else if (maj == 6 && min == 0)
PSUTIL_WINVER = PSUTIL_WINDOWS_VISTA; // or Server 2008
else if (maj == 6 && min == 1)
PSUTIL_WINVER = PSUTIL_WINDOWS_7;
else if (maj == 6 && min == 2)
PSUTIL_WINVER = PSUTIL_WINDOWS_8;
else if (maj == 6 && min == 3)
PSUTIL_WINVER = PSUTIL_WINDOWS_8_1;
else if (maj == 10 && min == 0)
PSUTIL_WINVER = PSUTIL_WINDOWS_10;
else
PSUTIL_WINVER = PSUTIL_WINDOWS_NEW;
return 0;
}
static int
psutil_load_sysinfo() {
GetSystemInfo(&PSUTIL_SYSTEM_INFO);
return 0;
}
int
psutil_load_globals() {
if (psutil_loadlibs() != 0)
return 1;
if (psutil_set_winver() != 0)
return 1;
if (psutil_load_sysinfo() != 0)
return 1;
return 0;
}

Просмотреть файл

@ -1,77 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
* List of constants and objects that are globally available.
*/
#include <windows.h>
#include "ntextapi.h"
extern int PSUTIL_WINVER;
extern SYSTEM_INFO PSUTIL_SYSTEM_INFO;
#define PSUTIL_WINDOWS_XP 51
#define PSUTIL_WINDOWS_SERVER_2003 52
#define PSUTIL_WINDOWS_VISTA 60
#define PSUTIL_WINDOWS_7 61
#define PSUTIL_WINDOWS_8 62
#define PSUTIL_WINDOWS_8_1 63
#define PSUTIL_WINDOWS_10 100
#define PSUTIL_WINDOWS_NEW MAXLONG
int psutil_load_globals();
PVOID psutil_GetProcAddress(LPCSTR libname, LPCSTR procname);
PVOID psutil_GetProcAddressFromLib(LPCSTR libname, LPCSTR procname);
PVOID psutil_SetFromNTStatusErr(NTSTATUS Status, const char *syscall);
_NtQuerySystemInformation \
psutil_NtQuerySystemInformation;
_NtQueryInformationProcess \
psutil_NtQueryInformationProcess;
_NtSetInformationProcess
psutil_NtSetInformationProcess;
_WinStationQueryInformationW \
psutil_WinStationQueryInformationW;
_RtlIpv4AddressToStringA \
psutil_rtlIpv4AddressToStringA;
_RtlIpv6AddressToStringA \
psutil_rtlIpv6AddressToStringA;
_GetExtendedTcpTable \
psutil_GetExtendedTcpTable;
_GetExtendedUdpTable \
psutil_GetExtendedUdpTable;
_GetActiveProcessorCount \
psutil_GetActiveProcessorCount;
_GetTickCount64 \
psutil_GetTickCount64;
_NtQueryObject \
psutil_NtQueryObject;
_GetLogicalProcessorInformationEx \
psutil_GetLogicalProcessorInformationEx;
_RtlGetVersion \
psutil_RtlGetVersion;
_NtSuspendProcess \
psutil_NtSuspendProcess;
_NtResumeProcess \
psutil_NtResumeProcess;
_NtQueryVirtualMemory \
psutil_NtQueryVirtualMemory;
_RtlNtStatusToDosErrorNoTeb \
psutil_RtlNtStatusToDosErrorNoTeb;

Просмотреть файл

@ -1,45 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include "inet_ntop.h"
// From: https://memset.wordpress.com/2010/10/09/inet_ntop-for-win32/
PCSTR WSAAPI
inet_ntop(INT family, PVOID pAddr, PSTR stringBuf, size_t strBufSize) {
DWORD dwAddressLength = 0;
struct sockaddr_storage srcaddr;
struct sockaddr_in *srcaddr4 = (struct sockaddr_in*) &srcaddr;
struct sockaddr_in6 *srcaddr6 = (struct sockaddr_in6*) &srcaddr;
memset(&srcaddr, 0, sizeof(struct sockaddr_storage));
srcaddr.ss_family = family;
if (family == AF_INET) {
dwAddressLength = sizeof(struct sockaddr_in);
memcpy(&(srcaddr4->sin_addr), pAddr, sizeof(struct in_addr));
}
else if (family == AF_INET6) {
dwAddressLength = sizeof(struct sockaddr_in6);
memcpy(&(srcaddr6->sin6_addr), pAddr, sizeof(struct in6_addr));
}
else {
PyErr_SetString(PyExc_ValueError, "invalid family");
return NULL;
}
if (WSAAddressToStringA(
(LPSOCKADDR) &srcaddr,
dwAddressLength,
0,
stringBuf,
(LPDWORD) &strBufSize) != 0)
{
PyErr_SetExcFromWindowsErr(PyExc_OSError, WSAGetLastError());
return NULL;
}
return stringBuf;
}

Просмотреть файл

@ -1,17 +0,0 @@
/*
* Copyright (c) 2009, Giampaolo Rodola', Jeff Tang. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// because of WSAAddressToStringA
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <ws2tcpip.h>
PCSTR WSAAPI
inet_ntop(
__in INT Family,
__in const VOID * pAddr,
__out_ecount(StringBufSize) PSTR pStringBuf,
__in size_t StringBufSize
);

443
third_party/python/psutil/psutil/arch/windows/net.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,443 @@
/*
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// Fixes clash between winsock2.h and windows.h
#define WIN32_LEAN_AND_MEAN
#include <Python.h>
#include <windows.h>
#include <wchar.h>
#include <ws2tcpip.h>
#include "../../_psutil_common.h"
static PIP_ADAPTER_ADDRESSES
psutil_get_nic_addresses() {
// allocate a 15 KB buffer to start with
int outBufLen = 15000;
DWORD dwRetVal = 0;
ULONG attempts = 0;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
do {
pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
if (pAddresses == NULL) {
PyErr_NoMemory();
return NULL;
}
dwRetVal = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses,
&outBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
free(pAddresses);
pAddresses = NULL;
}
else {
break;
}
attempts++;
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (attempts < 3));
if (dwRetVal != NO_ERROR) {
PyErr_SetString(
PyExc_RuntimeError, "GetAdaptersAddresses() syscall failed.");
return NULL;
}
return pAddresses;
}
/*
* Return a Python list of named tuples with overall network I/O information
*/
PyObject *
psutil_net_io_counters(PyObject *self, PyObject *args) {
DWORD dwRetVal = 0;
MIB_IF_ROW2 *pIfRow = NULL;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_nic_info = NULL;
PyObject *py_nic_name = NULL;
if (py_retdict == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
py_nic_name = NULL;
py_nic_info = NULL;
pIfRow = (MIB_IF_ROW2 *) malloc(sizeof(MIB_IF_ROW2));
if (pIfRow == NULL) {
PyErr_NoMemory();
goto error;
}
SecureZeroMemory((PVOID)pIfRow, sizeof(MIB_IF_ROW2));
pIfRow->InterfaceIndex = pCurrAddresses->IfIndex;
dwRetVal = GetIfEntry2(pIfRow);
if (dwRetVal != NO_ERROR) {
PyErr_SetString(PyExc_RuntimeError,
"GetIfEntry() or GetIfEntry2() syscalls failed.");
goto error;
}
py_nic_info = Py_BuildValue(
"(KKKKKKKK)",
pIfRow->OutOctets,
pIfRow->InOctets,
(pIfRow->OutUcastPkts + pIfRow->OutNUcastPkts),
(pIfRow->InUcastPkts + pIfRow->InNUcastPkts),
pIfRow->InErrors,
pIfRow->OutErrors,
pIfRow->InDiscards,
pIfRow->OutDiscards);
if (!py_nic_info)
goto error;
py_nic_name = PyUnicode_FromWideChar(
pCurrAddresses->FriendlyName,
wcslen(pCurrAddresses->FriendlyName));
if (py_nic_name == NULL)
goto error;
if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info))
goto error;
Py_CLEAR(py_nic_name);
Py_CLEAR(py_nic_info);
free(pIfRow);
pCurrAddresses = pCurrAddresses->Next;
}
free(pAddresses);
return py_retdict;
error:
Py_XDECREF(py_nic_name);
Py_XDECREF(py_nic_info);
Py_DECREF(py_retdict);
if (pAddresses != NULL)
free(pAddresses);
if (pIfRow != NULL)
free(pIfRow);
return NULL;
}
/*
* Return NICs addresses.
*/
PyObject *
psutil_net_if_addrs(PyObject *self, PyObject *args) {
unsigned int i = 0;
ULONG family;
PCTSTR intRet;
PCTSTR netmaskIntRet;
char *ptr;
char buff_addr[1024];
char buff_macaddr[1024];
char buff_netmask[1024];
DWORD dwRetVal = 0;
ULONG converted_netmask;
UINT netmask_bits;
struct in_addr in_netmask;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_address = NULL;
PyObject *py_mac_address = NULL;
PyObject *py_nic_name = NULL;
PyObject *py_netmask = NULL;
if (py_retlist == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
pUnicast = pCurrAddresses->FirstUnicastAddress;
netmaskIntRet = NULL;
py_nic_name = NULL;
py_nic_name = PyUnicode_FromWideChar(
pCurrAddresses->FriendlyName,
wcslen(pCurrAddresses->FriendlyName));
if (py_nic_name == NULL)
goto error;
// MAC address
if (pCurrAddresses->PhysicalAddressLength != 0) {
ptr = buff_macaddr;
*ptr = '\0';
for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) {
if (i == (pCurrAddresses->PhysicalAddressLength - 1)) {
sprintf_s(ptr, _countof(buff_macaddr), "%.2X\n",
(int)pCurrAddresses->PhysicalAddress[i]);
}
else {
sprintf_s(ptr, _countof(buff_macaddr), "%.2X-",
(int)pCurrAddresses->PhysicalAddress[i]);
}
ptr += 3;
}
*--ptr = '\0';
py_mac_address = Py_BuildValue("s", buff_macaddr);
if (py_mac_address == NULL)
goto error;
Py_INCREF(Py_None);
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_tuple = Py_BuildValue(
"(OiOOOO)",
py_nic_name,
-1, // this will be converted later to AF_LINK
py_mac_address,
Py_None, // netmask (not supported)
Py_None, // broadcast (not supported)
Py_None // ptp (not supported on Windows)
);
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_CLEAR(py_tuple);
Py_CLEAR(py_mac_address);
}
// find out the IP address associated with the NIC
if (pUnicast != NULL) {
for (i = 0; pUnicast != NULL; i++) {
family = pUnicast->Address.lpSockaddr->sa_family;
if (family == AF_INET) {
struct sockaddr_in *sa_in = (struct sockaddr_in *)
pUnicast->Address.lpSockaddr;
intRet = inet_ntop(AF_INET, &(sa_in->sin_addr), buff_addr,
sizeof(buff_addr));
if (!intRet)
goto error;
netmask_bits = pUnicast->OnLinkPrefixLength;
dwRetVal = ConvertLengthToIpv4Mask(
netmask_bits, &converted_netmask);
if (dwRetVal == NO_ERROR) {
in_netmask.s_addr = converted_netmask;
netmaskIntRet = inet_ntop(
AF_INET, &in_netmask, buff_netmask,
sizeof(buff_netmask));
if (!netmaskIntRet)
goto error;
}
}
else if (family == AF_INET6) {
struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)
pUnicast->Address.lpSockaddr;
intRet = inet_ntop(AF_INET6, &(sa_in6->sin6_addr),
buff_addr, sizeof(buff_addr));
if (!intRet)
goto error;
}
else {
// we should never get here
pUnicast = pUnicast->Next;
continue;
}
#if PY_MAJOR_VERSION >= 3
py_address = PyUnicode_FromString(buff_addr);
#else
py_address = PyString_FromString(buff_addr);
#endif
if (py_address == NULL)
goto error;
if (netmaskIntRet != NULL) {
#if PY_MAJOR_VERSION >= 3
py_netmask = PyUnicode_FromString(buff_netmask);
#else
py_netmask = PyString_FromString(buff_netmask);
#endif
} else {
Py_INCREF(Py_None);
py_netmask = Py_None;
}
Py_INCREF(Py_None);
Py_INCREF(Py_None);
py_tuple = Py_BuildValue(
"(OiOOOO)",
py_nic_name,
family,
py_address,
py_netmask,
Py_None, // broadcast (not supported)
Py_None // ptp (not supported on Windows)
);
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_CLEAR(py_tuple);
Py_CLEAR(py_address);
Py_CLEAR(py_netmask);
pUnicast = pUnicast->Next;
}
}
Py_CLEAR(py_nic_name);
pCurrAddresses = pCurrAddresses->Next;
}
free(pAddresses);
return py_retlist;
error:
if (pAddresses)
free(pAddresses);
Py_DECREF(py_retlist);
Py_XDECREF(py_tuple);
Py_XDECREF(py_address);
Py_XDECREF(py_nic_name);
Py_XDECREF(py_netmask);
return NULL;
}
/*
* Provides stats about NIC interfaces installed on the system.
* TODO: get 'duplex' (currently it's hard coded to '2', aka
'full duplex')
*/
PyObject *
psutil_net_if_stats(PyObject *self, PyObject *args) {
int i;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
MIB_IFTABLE *pIfTable;
MIB_IFROW *pIfRow;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
char descr[MAX_PATH];
int ifname_found;
PyObject *py_nic_name = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_ifc_info = NULL;
PyObject *py_is_up = NULL;
if (py_retdict == NULL)
return NULL;
pAddresses = psutil_get_nic_addresses();
if (pAddresses == NULL)
goto error;
pIfTable = (MIB_IFTABLE *) malloc(sizeof (MIB_IFTABLE));
if (pIfTable == NULL) {
PyErr_NoMemory();
goto error;
}
dwSize = sizeof(MIB_IFTABLE);
if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) {
free(pIfTable);
pIfTable = (MIB_IFTABLE *) malloc(dwSize);
if (pIfTable == NULL) {
PyErr_NoMemory();
goto error;
}
}
// Make a second call to GetIfTable to get the actual
// data we want.
if ((dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE)) != NO_ERROR) {
PyErr_SetString(PyExc_RuntimeError, "GetIfTable() syscall failed");
goto error;
}
for (i = 0; i < (int) pIfTable->dwNumEntries; i++) {
pIfRow = (MIB_IFROW *) & pIfTable->table[i];
// GetIfTable is not able to give us NIC with "friendly names"
// so we determine them via GetAdapterAddresses() which
// provides friendly names *and* descriptions and find the
// ones that match.
ifname_found = 0;
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
sprintf_s(descr, MAX_PATH, "%wS", pCurrAddresses->Description);
if (lstrcmp(descr, pIfRow->bDescr) == 0) {
py_nic_name = PyUnicode_FromWideChar(
pCurrAddresses->FriendlyName,
wcslen(pCurrAddresses->FriendlyName));
if (py_nic_name == NULL)
goto error;
ifname_found = 1;
break;
}
pCurrAddresses = pCurrAddresses->Next;
}
if (ifname_found == 0) {
// Name not found means GetAdapterAddresses() doesn't list
// this NIC, only GetIfTable, meaning it's not really a NIC
// interface so we skip it.
continue;
}
// is up?
if ((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) &&
pIfRow->dwAdminStatus == 1 ) {
py_is_up = Py_True;
}
else {
py_is_up = Py_False;
}
Py_INCREF(py_is_up);
py_ifc_info = Py_BuildValue(
"(Oikk)",
py_is_up,
2, // there's no way to know duplex so let's assume 'full'
pIfRow->dwSpeed / 1000000, // expressed in bytes, we want Mb
pIfRow->dwMtu
);
if (!py_ifc_info)
goto error;
if (PyDict_SetItem(py_retdict, py_nic_name, py_ifc_info))
goto error;
Py_CLEAR(py_nic_name);
Py_CLEAR(py_ifc_info);
}
free(pIfTable);
free(pAddresses);
return py_retdict;
error:
Py_XDECREF(py_is_up);
Py_XDECREF(py_ifc_info);
Py_XDECREF(py_nic_name);
Py_DECREF(py_retdict);
if (pIfTable != NULL)
free(pIfTable);
if (pAddresses != NULL)
free(pAddresses);
return NULL;
}

11
third_party/python/psutil/psutil/arch/windows/net.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,11 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
PyObject *psutil_net_if_addrs(PyObject *self, PyObject *args);
PyObject *psutil_net_if_stats(PyObject *self, PyObject *args);
PyObject *psutil_net_io_counters(PyObject *self, PyObject *args);

Просмотреть файл

@ -2,7 +2,9 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
* Define Windows structs and constants which are considered private.
*/
#if !defined(__NTEXTAPI_H__)
#define __NTEXTAPI_H__
#include <winternl.h>
@ -10,74 +12,92 @@
typedef LONG NTSTATUS;
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
#define STATUS_BUFFER_TOO_SMALL 0xC0000023L
#define SystemExtendedHandleInformation 64
#define MemoryWorkingSetInformation 0x1
// https://github.com/ajkhoury/TestDll/blob/master/nt_ddk.h
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
/*
* ================================================================
* Enums.
* ================================================================
*/
// ================================================================
// Enums
// ================================================================
typedef enum _PROCESSINFOCLASS2 {
_ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
_ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
_ProcessWow64Information,
/* added after XP+ */
_ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
_ProcessBreakOnTermination,
ProcessDebugObjectHandle,
ProcessDebugFlags,
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessResourceManagement,
ProcessCookie,
ProcessImageInformation,
MaxProcessInfoClass
} PROCESSINFOCLASS2;
#undef SystemExtendedHandleInformation
#define SystemExtendedHandleInformation 64
#undef MemoryWorkingSetInformation
#define MemoryWorkingSetInformation 0x1
#undef ObjectNameInformation
#define ObjectNameInformation 1
#undef ProcessIoPriority
#define ProcessIoPriority 33
#undef ProcessWow64Information
#define ProcessWow64Information 26
#undef SystemProcessIdInformation
#define SystemProcessIdInformation 88
#define PROCESSINFOCLASS PROCESSINFOCLASS2
#define ProcessBasicInformation _ProcessBasicInformation
#define ProcessWow64Information _ProcessWow64Information
#define ProcessDebugPort _ProcessDebugPort
#define ProcessImageFileName _ProcessImageFileName
#define ProcessBreakOnTermination _ProcessBreakOnTermination
// process suspend() / resume()
typedef enum _KTHREAD_STATE {
Initialized,
Ready,
Running,
Standby,
Terminated,
Waiting,
Transition,
DeferredReady,
GateWait,
MaximumThreadState
} KTHREAD_STATE, *PKTHREAD_STATE;
/*
* ================================================================
* Structs.
* ================================================================
*/
typedef enum _KWAIT_REASON {
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
WrKeyedEvent,
WrTerminated,
WrProcessInSwap,
WrCpuRateControl,
WrCalloutStack,
WrKernel,
WrResource,
WrPushLock,
WrMutex,
WrQuantumEnd,
WrDispatchInt,
WrPreempted,
WrYieldExecution,
WrFastMutex,
WrGuardedMutex,
WrRundown,
WrAlertByThreadId,
WrDeferredPreempt,
MaximumWaitReason
} KWAIT_REASON, *PKWAIT_REASON;
// ================================================================
// Structs.
// ================================================================
// cpu_stats(), per_cpu_times()
typedef struct {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
@ -87,6 +107,7 @@ typedef struct {
ULONG InterruptCount;
} _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
// cpu_stats()
typedef struct {
LARGE_INTEGER IdleProcessTime;
LARGE_INTEGER IoReadTransferCount;
@ -164,6 +185,7 @@ typedef struct {
ULONG SystemCalls;
} _SYSTEM_PERFORMANCE_INFORMATION;
// cpu_stats()
typedef struct {
ULONG ContextSwitches;
ULONG DpcCount;
@ -173,62 +195,6 @@ typedef struct {
ULONG ApcBypassCount;
} _SYSTEM_INTERRUPT_INFORMATION;
typedef enum _KTHREAD_STATE {
Initialized,
Ready,
Running,
Standby,
Terminated,
Waiting,
Transition,
DeferredReady,
GateWait,
MaximumThreadState
} KTHREAD_STATE, *PKTHREAD_STATE;
typedef enum _KWAIT_REASON {
Executive,
FreePage,
PageIn,
PoolAllocation,
DelayExecution,
Suspended,
UserRequest,
WrExecutive,
WrFreePage,
WrPageIn,
WrPoolAllocation,
WrDelayExecution,
WrSuspended,
WrUserRequest,
WrEventPair,
WrQueue,
WrLpcReceive,
WrLpcReply,
WrVirtualMemory,
WrPageOut,
WrRendezvous,
WrKeyedEvent,
WrTerminated,
WrProcessInSwap,
WrCpuRateControl,
WrCalloutStack,
WrKernel,
WrResource,
WrPushLock,
WrMutex,
WrQuantumEnd,
WrDispatchInt,
WrPreempted,
WrYieldExecution,
WrFastMutex,
WrGuardedMutex,
WrRundown,
WrAlertByThreadId,
WrDeferredPreempt,
MaximumWaitReason
} KWAIT_REASON, *PKWAIT_REASON;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX {
PVOID Object;
HANDLE UniqueProcessId;
@ -271,19 +237,6 @@ typedef struct _SYSTEM_THREAD_INFORMATION2 {
#define SYSTEM_THREAD_INFORMATION SYSTEM_THREAD_INFORMATION2
#define PSYSTEM_THREAD_INFORMATION PSYSTEM_THREAD_INFORMATION2
typedef struct _TEB *PTEB;
typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
SYSTEM_THREAD_INFORMATION ThreadInfo;
PVOID StackBase;
PVOID StackLimit;
PVOID Win32StartAddress;
PTEB TebBase;
ULONG_PTR Reserved2;
ULONG_PTR Reserved3;
ULONG_PTR Reserved4;
} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION2 {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
@ -324,6 +277,7 @@ typedef struct _SYSTEM_PROCESS_INFORMATION2 {
#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2
#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2
// cpu_freq()
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
@ -342,7 +296,7 @@ typedef struct in6_addr {
} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR;
#endif
// http://msdn.microsoft.com/en-us/library/aa813741(VS.85).aspx
// PEB / cmdline(), cwd(), environ()
typedef struct {
BYTE Reserved1[16];
PVOID Reserved2[5];
@ -354,6 +308,7 @@ typedef struct {
LPCWSTR env;
} RTL_USER_PROCESS_PARAMETERS_, *PRTL_USER_PROCESS_PARAMETERS_;
// users()
typedef struct _WINSTATION_INFO {
BYTE Reserved1[72];
ULONG SessionId;
@ -366,6 +321,7 @@ typedef struct _WINSTATION_INFO {
FILETIME CurrentTime;
} WINSTATION_INFO, *PWINSTATION_INFO;
// cpu_count_phys()
#if (_WIN32_WINNT < 0x0601) // Windows < 7 (Vista and XP)
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
@ -377,9 +333,11 @@ typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX {
CACHE_RELATIONSHIP Cache;
GROUP_RELATIONSHIP Group;
} DUMMYUNIONNAME;
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, \
*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
#endif
// memory_uss()
typedef struct _MEMORY_WORKING_SET_BLOCK {
ULONG_PTR Protection : 5;
ULONG_PTR ShareCount : 3;
@ -392,11 +350,13 @@ typedef struct _MEMORY_WORKING_SET_BLOCK {
#endif
} MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK;
// memory_uss()
typedef struct _MEMORY_WORKING_SET_INFORMATION {
ULONG_PTR NumberOfEntries;
MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1];
} MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION;
// memory_uss()
typedef struct _PSUTIL_PROCESS_WS_COUNTERS {
SIZE_T NumberOfPages;
SIZE_T NumberOfPrivatePages;
@ -404,18 +364,122 @@ typedef struct _PSUTIL_PROCESS_WS_COUNTERS {
SIZE_T NumberOfShareablePages;
} PSUTIL_PROCESS_WS_COUNTERS, *PPSUTIL_PROCESS_WS_COUNTERS;
/*
* ================================================================
* Type defs for modules loaded at runtime.
* ================================================================
*/
// exe()
typedef struct _SYSTEM_PROCESS_ID_INFORMATION {
HANDLE ProcessId;
UNICODE_STRING ImageName;
} SYSTEM_PROCESS_ID_INFORMATION, *PSYSTEM_PROCESS_ID_INFORMATION;
typedef BOOL (WINAPI *_GetLogicalProcessorInformationEx)(
// ====================================================================
// PEB structs for cmdline(), cwd(), environ()
// ====================================================================
#ifdef _WIN64
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[21];
PVOID LoaderData;
PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters;
// more fields...
} PEB_;
// When we are a 64 bit process accessing a 32 bit (WoW64)
// process we need to use the 32 bit structure layout.
typedef struct {
USHORT Length;
USHORT MaxLength;
DWORD Buffer;
} UNICODE_STRING32;
typedef struct {
BYTE Reserved1[16];
DWORD Reserved2[5];
UNICODE_STRING32 CurrentDirectoryPath;
DWORD CurrentDirectoryHandle;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
DWORD env;
} RTL_USER_PROCESS_PARAMETERS32;
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
DWORD Reserved3[2];
DWORD Ldr;
DWORD ProcessParameters;
// more fields...
} PEB32;
#else // ! _WIN64
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PVOID Ldr;
PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters;
// more fields...
} PEB_;
// When we are a 32 bit (WoW64) process accessing a 64 bit process
// we need to use the 64 bit structure layout and a special function
// to read its memory.
typedef NTSTATUS (NTAPI *_NtWow64ReadVirtualMemory64)(
HANDLE ProcessHandle,
PVOID64 BaseAddress,
PVOID Buffer,
ULONG64 Size,
PULONG64 NumberOfBytesRead);
typedef struct {
PVOID Reserved1[2];
PVOID64 PebBaseAddress;
PVOID Reserved2[4];
PVOID UniqueProcessId[2];
PVOID Reserved3[2];
} PROCESS_BASIC_INFORMATION64;
typedef struct {
USHORT Length;
USHORT MaxLength;
PVOID64 Buffer;
} UNICODE_STRING64;
typedef struct {
BYTE Reserved1[16];
PVOID64 Reserved2[5];
UNICODE_STRING64 CurrentDirectoryPath;
PVOID64 CurrentDirectoryHandle;
UNICODE_STRING64 DllPath;
UNICODE_STRING64 ImagePathName;
UNICODE_STRING64 CommandLine;
PVOID64 env;
} RTL_USER_PROCESS_PARAMETERS64;
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[21];
PVOID64 LoaderData;
PVOID64 ProcessParameters;
// more fields...
} PEB64;
#endif // _WIN64
// ================================================================
// Type defs for modules loaded at runtime.
// ================================================================
BOOL (WINAPI *_GetLogicalProcessorInformationEx) (
LOGICAL_PROCESSOR_RELATIONSHIP relationship,
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer,
PDWORD ReturnLength);
typedef BOOLEAN (WINAPI * _WinStationQueryInformationW)(
#define GetLogicalProcessorInformationEx _GetLogicalProcessorInformationEx
BOOLEAN (WINAPI * _WinStationQueryInformationW) (
HANDLE ServerHandle,
ULONG SessionId,
WINSTATIONINFOCLASS WinStationInformationClass,
@ -423,34 +487,46 @@ typedef BOOLEAN (WINAPI * _WinStationQueryInformationW)(
ULONG WinStationInformationLength,
PULONG pReturnLength);
typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
#define WinStationQueryInformationW _WinStationQueryInformationW
NTSTATUS (NTAPI *_NtQueryInformationProcess) (
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength);
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
#define NtQueryInformationProcess _NtQueryInformationProcess
NTSTATUS (NTAPI *_NtQuerySystemInformation) (
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
#define NtQuerySystemInformation _NtQuerySystemInformation
NTSTATUS (NTAPI *_NtSetInformationProcess) (
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
PVOID ProcessInformation,
DWORD ProcessInformationLength);
typedef PSTR (NTAPI * _RtlIpv4AddressToStringA)(
#define NtSetInformationProcess _NtSetInformationProcess
PSTR (NTAPI * _RtlIpv4AddressToStringA) (
struct in_addr *Addr,
PSTR S);
typedef PSTR (NTAPI * _RtlIpv6AddressToStringA)(
#define RtlIpv4AddressToStringA _RtlIpv4AddressToStringA
PSTR (NTAPI * _RtlIpv6AddressToStringA) (
struct in6_addr *Addr,
PSTR P);
typedef DWORD (WINAPI * _GetExtendedTcpTable)(
#define RtlIpv6AddressToStringA _RtlIpv6AddressToStringA
DWORD (WINAPI * _GetExtendedTcpTable) (
PVOID pTcpTable,
PDWORD pdwSize,
BOOL bOrder,
@ -458,7 +534,9 @@ typedef DWORD (WINAPI * _GetExtendedTcpTable)(
TCP_TABLE_CLASS TableClass,
ULONG Reserved);
typedef DWORD (WINAPI * _GetExtendedUdpTable)(
#define GetExtendedTcpTable _GetExtendedTcpTable
DWORD (WINAPI * _GetExtendedUdpTable) (
PVOID pUdpTable,
PDWORD pdwSize,
BOOL bOrder,
@ -466,32 +544,46 @@ typedef DWORD (WINAPI * _GetExtendedUdpTable)(
UDP_TABLE_CLASS TableClass,
ULONG Reserved);
typedef DWORD (CALLBACK *_GetActiveProcessorCount)(
#define GetExtendedUdpTable _GetExtendedUdpTable
DWORD (CALLBACK *_GetActiveProcessorCount) (
WORD GroupNumber);
typedef ULONGLONG (CALLBACK *_GetTickCount64)(
#define GetActiveProcessorCount _GetActiveProcessorCount
ULONGLONG (CALLBACK *_GetTickCount64) (
void);
typedef NTSTATUS (NTAPI *_NtQueryObject)(
#define GetTickCount64 _GetTickCount64
NTSTATUS (NTAPI *_NtQueryObject) (
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength);
typedef NTSTATUS (WINAPI *_RtlGetVersion) (
#define NtQueryObject _NtQueryObject
NTSTATUS (WINAPI *_RtlGetVersion) (
PRTL_OSVERSIONINFOW lpVersionInformation
);
typedef NTSTATUS (WINAPI *_NtResumeProcess) (
#define RtlGetVersion _RtlGetVersion
NTSTATUS (WINAPI *_NtResumeProcess) (
HANDLE hProcess
);
typedef NTSTATUS (WINAPI *_NtSuspendProcess) (
#define NtResumeProcess _NtResumeProcess
NTSTATUS (WINAPI *_NtSuspendProcess) (
HANDLE hProcess
);
typedef NTSTATUS (NTAPI *_NtQueryVirtualMemory) (
#define NtSuspendProcess _NtSuspendProcess
NTSTATUS (NTAPI *_NtQueryVirtualMemory) (
HANDLE ProcessHandle,
PVOID BaseAddress,
int MemoryInformationClass,
@ -500,8 +592,12 @@ typedef NTSTATUS (NTAPI *_NtQueryVirtualMemory) (
PSIZE_T ReturnLength
);
typedef ULONG (WINAPI *_RtlNtStatusToDosErrorNoTeb) (
#define NtQueryVirtualMemory _NtQueryVirtualMemory
ULONG (WINAPI *_RtlNtStatusToDosErrorNoTeb) (
NTSTATUS status
);
#define RtlNtStatusToDosErrorNoTeb _RtlNtStatusToDosErrorNoTeb
#endif // __NTEXTAPI_H__

Просмотреть файл

@ -2,512 +2,291 @@
* Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/*
* This module retrieves handles opened by a process.
* We use NtQuerySystemInformation to enumerate them and NtQueryObject
* to obtain the corresponding file name.
* Since NtQueryObject hangs for certain handle types we call it in a
* separate thread which gets killed if it doesn't complete within 100ms.
* This is a limitation of the Windows API and ProcessHacker uses the
* same trick: https://github.com/giampaolo/psutil/pull/597
*
* CREDITS: original implementation was written by Jeff Tang.
* It was then rewritten by Giampaolo Rodola many years later.
* Utility functions for getting the file handles and names were re-adapted
* from the excellent ProcessHacker.
*/
#include <windows.h>
#include <Psapi.h>
#include <Python.h>
#include "ntextapi.h"
#include "global.h"
#include "process_handles.h"
#include "process_info.h"
#include "../../_psutil_common.h"
CRITICAL_SECTION g_cs;
BOOL g_initialized = FALSE;
NTSTATUS g_status;
HANDLE g_hFile = NULL;
HANDLE g_hEvtStart = NULL;
HANDLE g_hEvtFinish = NULL;
HANDLE g_hThread = NULL;
PUNICODE_STRING g_pNameBuffer = NULL;
ULONG g_dwSize = 0;
ULONG g_dwLength = 0;
#include "process_utils.h"
#define ObjectNameInformation 1
#define NTQO_TIMEOUT 100
#define THREAD_TIMEOUT 100 // ms
// Global object shared between the 2 threads.
PUNICODE_STRING globalFileName = NULL;
static VOID
psutil_get_open_files_init(BOOL threaded) {
if (g_initialized == TRUE)
return;
static int
psutil_enum_handles(PSYSTEM_HANDLE_INFORMATION_EX *handles) {
static ULONG initialBufferSize = 0x10000;
NTSTATUS status;
PVOID buffer;
ULONG bufferSize;
// Create events for signalling work between threads
if (threaded == TRUE) {
g_hEvtStart = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hEvtFinish = CreateEvent(NULL, FALSE, FALSE, NULL);
InitializeCriticalSection(&g_cs);
bufferSize = initialBufferSize;
buffer = MALLOC_ZERO(bufferSize);
if (buffer == NULL) {
PyErr_NoMemory();
return 1;
}
g_initialized = TRUE;
while ((status = NtQuerySystemInformation(
SystemExtendedHandleInformation,
buffer,
bufferSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
FREE(buffer);
bufferSize *= 2;
// Fail if we're resizing the buffer to something very large.
if (bufferSize > 256 * 1024 * 1024) {
PyErr_SetString(
PyExc_RuntimeError,
"SystemExtendedHandleInformation buffer too big");
return 1;
}
buffer = MALLOC_ZERO(bufferSize);
if (buffer == NULL) {
PyErr_NoMemory();
return 1;
}
}
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation");
FREE(buffer);
return 1;
}
*handles = (PSYSTEM_HANDLE_INFORMATION_EX)buffer;
return 0;
}
static DWORD WINAPI
psutil_wait_thread(LPVOID lpvParam) {
// Loop infinitely waiting for work
while (TRUE) {
WaitForSingleObject(g_hEvtStart, INFINITE);
static int
psutil_get_filename(LPVOID lpvParam) {
HANDLE hFile = *((HANDLE*)lpvParam);
NTSTATUS status;
ULONG bufferSize;
ULONG attempts = 8;
// TODO: return code not checked
g_status = psutil_NtQueryObject(
g_hFile,
ObjectNameInformation,
g_pNameBuffer,
g_dwSize,
&g_dwLength);
SetEvent(g_hEvtFinish);
bufferSize = 0x200;
globalFileName = MALLOC_ZERO(bufferSize);
if (globalFileName == NULL) {
PyErr_NoMemory();
goto error;
}
// Note: also this is supposed to hang, hence why we do it in here.
if (GetFileType(hFile) != FILE_TYPE_DISK) {
SetLastError(0);
globalFileName->Length = 0;
return 0;
}
// A loop is needed because the I/O subsystem likes to give us the
// wrong return lengths...
do {
status = NtQueryObject(
hFile,
ObjectNameInformation,
globalFileName,
bufferSize,
&bufferSize
);
if (status == STATUS_BUFFER_OVERFLOW ||
status == STATUS_INFO_LENGTH_MISMATCH ||
status == STATUS_BUFFER_TOO_SMALL)
{
FREE(globalFileName);
globalFileName = MALLOC_ZERO(bufferSize);
if (globalFileName == NULL) {
PyErr_NoMemory();
goto error;
}
}
else {
break;
}
} while (--attempts);
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(status, "NtQuerySystemInformation");
FREE(globalFileName);
globalFileName = NULL;
return 1;
}
return 0;
error:
if (globalFileName != NULL) {
FREE(globalFileName);
globalFileName = NULL;
}
return 1;
}
static DWORD
psutil_create_thread() {
DWORD dwWait = 0;
psutil_threaded_get_filename(HANDLE hFile) {
DWORD dwWait;
HANDLE hThread;
DWORD threadRetValue;
if (g_hThread == NULL)
g_hThread = CreateThread(
NULL,
0,
psutil_wait_thread,
NULL,
0,
NULL);
if (g_hThread == NULL)
return GetLastError();
hThread = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)psutil_get_filename, &hFile, 0, NULL);
if (hThread == NULL) {
PyErr_SetFromOSErrnoWithSyscall("CreateThread");
return 1;
}
// Signal the worker thread to start
SetEvent(g_hEvtStart);
// Wait for the worker thread to finish.
dwWait = WaitForSingleObject(hThread, THREAD_TIMEOUT);
// Wait for the worker thread to finish
dwWait = WaitForSingleObject(g_hEvtFinish, NTQO_TIMEOUT);
// If the thread hangs, kill it and cleanup
// If the thread hangs, kill it and cleanup.
if (dwWait == WAIT_TIMEOUT) {
SuspendThread(g_hThread);
TerminateThread(g_hThread, 1);
WaitForSingleObject(g_hThread, INFINITE);
CloseHandle(g_hThread);
g_hThread = NULL;
psutil_debug(
"get handle name thread timed out after %i ms", THREAD_TIMEOUT);
if (TerminateThread(hThread, 0) == 0) {
PyErr_SetFromOSErrnoWithSyscall("TerminateThread");
CloseHandle(hThread);
return 1;
}
CloseHandle(hThread);
return 0;
}
return dwWait;
if (dwWait == WAIT_FAILED) {
psutil_debug("WaitForSingleObject -> WAIT_FAILED");
if (TerminateThread(hThread, 0) == 0) {
PyErr_SetFromOSErrnoWithSyscall(
"WaitForSingleObject -> WAIT_FAILED -> TerminateThread");
CloseHandle(hThread);
return 1;
}
PyErr_SetFromOSErrnoWithSyscall("WaitForSingleObject");
CloseHandle(hThread);
return 1;
}
if (GetExitCodeThread(hThread, &threadRetValue) == 0) {
if (TerminateThread(hThread, 0) == 0) {
PyErr_SetFromOSErrnoWithSyscall(
"GetExitCodeThread (failed) -> TerminateThread");
CloseHandle(hThread);
return 1;
}
CloseHandle(hThread);
PyErr_SetFromOSErrnoWithSyscall("GetExitCodeThread");
return 1;
}
CloseHandle(hThread);
return threadRetValue;
}
static PyObject *
psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess) {
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL;
DWORD dwInfoSize = 0x10000;
DWORD dwRet = 0;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL;
DWORD i = 0;
BOOLEAN error = FALSE;
DWORD dwWait = 0;
PyObject* py_retlist = NULL;
PyObject* py_path = NULL;
if (g_initialized == FALSE)
psutil_get_open_files_init(TRUE);
// Due to the use of global variables, ensure only 1 call
// to psutil_get_open_files() is running
EnterCriticalSection(&g_cs);
if (g_hEvtStart == NULL ||
g_hEvtFinish == NULL)
{
PyErr_SetFromWindowsErr(0);
error = TRUE;
goto cleanup;
}
// Py_BuildValue raises an exception if NULL is returned
py_retlist = PyList_New(0);
if (py_retlist == NULL) {
error = TRUE;
goto cleanup;
}
do {
if (pHandleInfo != NULL) {
HeapFree(GetProcessHeap(), 0, pHandleInfo);
pHandleInfo = NULL;
}
// NtQuerySystemInformation won't give us the correct buffer size,
// so we guess by doubling the buffer size.
dwInfoSize *= 2;
pHandleInfo = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwInfoSize);
if (pHandleInfo == NULL) {
PyErr_NoMemory();
error = TRUE;
goto cleanup;
}
} while ((status = psutil_NtQuerySystemInformation(
SystemExtendedHandleInformation,
pHandleInfo,
dwInfoSize,
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status, "NtQuerySystemInformation(SystemExtendedHandleInformation)");
error = TRUE;
goto cleanup;
}
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
hHandle = &pHandleInfo->Handles[i];
// Check if this hHandle belongs to the PID the user specified.
if (hHandle->UniqueProcessId != (ULONG_PTR)dwPid)
goto loop_cleanup;
if (!DuplicateHandle(hProcess,
(HANDLE)hHandle->HandleValue,
GetCurrentProcess(),
&g_hFile,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
{
/*
printf("[%d] DuplicateHandle (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
goto loop_cleanup;
}
// Guess buffer size is MAX_PATH + 1
g_dwLength = (MAX_PATH+1) * sizeof(WCHAR);
do {
// Release any previously allocated buffer
if (g_pNameBuffer != NULL) {
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
g_pNameBuffer = NULL;
g_dwSize = 0;
}
// NtQueryObject puts the required buffer size in g_dwLength
// WinXP edge case puts g_dwLength == 0, just skip this handle
if (g_dwLength == 0)
goto loop_cleanup;
g_dwSize = g_dwLength;
if (g_dwSize > 0) {
g_pNameBuffer = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
g_dwSize);
if (g_pNameBuffer == NULL)
goto loop_cleanup;
}
dwWait = psutil_create_thread();
// If the call does not return, skip this handle
if (dwWait != WAIT_OBJECT_0)
goto loop_cleanup;
} while (g_status == STATUS_INFO_LENGTH_MISMATCH);
// NtQueryObject stopped returning STATUS_INFO_LENGTH_MISMATCH
if (!NT_SUCCESS(g_status))
goto loop_cleanup;
// Convert to PyUnicode and append it to the return list
if (g_pNameBuffer->Length > 0) {
/*
printf("[%d] Filename (%#x) %#d bytes: %S\n",
dwPid,
hHandle->HandleValue,
g_pNameBuffer->Length,
g_pNameBuffer->Buffer);
*/
py_path = PyUnicode_FromWideChar(g_pNameBuffer->Buffer,
g_pNameBuffer->Length/2);
if (py_path == NULL) {
/*
printf("[%d] PyUnicode_FromWideChar (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
if (PyList_Append(py_retlist, py_path)) {
/*
printf("[%d] PyList_Append (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
}
loop_cleanup:
Py_XDECREF(py_path);
py_path = NULL;
if (g_pNameBuffer != NULL)
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
g_pNameBuffer = NULL;
g_dwSize = 0;
g_dwLength = 0;
if (g_hFile != NULL)
CloseHandle(g_hFile);
g_hFile = NULL;
}
cleanup:
if (g_pNameBuffer != NULL)
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
g_pNameBuffer = NULL;
g_dwSize = 0;
g_dwLength = 0;
if (g_hFile != NULL)
CloseHandle(g_hFile);
g_hFile = NULL;
if (pHandleInfo != NULL)
HeapFree(GetProcessHeap(), 0, pHandleInfo);
pHandleInfo = NULL;
if (error) {
Py_XDECREF(py_retlist);
py_retlist = NULL;
}
LeaveCriticalSection(&g_cs);
return py_retlist;
}
static PyObject *
psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess) {
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL;
DWORD dwInfoSize = 0x10000;
DWORD dwRet = 0;
PyObject *
psutil_get_open_files(DWORD dwPid, HANDLE hProcess) {
PSYSTEM_HANDLE_INFORMATION_EX handlesList = NULL;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL;
HANDLE hFile = NULL;
HANDLE hMap = NULL;
DWORD i = 0;
BOOLEAN error = FALSE;
PyObject* py_retlist = NULL;
ULONG i = 0;
BOOLEAN errorOccurred = FALSE;
PyObject* py_path = NULL;
ULONG dwSize = 0;
LPVOID pMem = NULL;
wchar_t pszFilename[MAX_PATH+1];
PyObject* py_retlist = PyList_New(0);;
if (g_initialized == FALSE)
psutil_get_open_files_init(FALSE);
if (!py_retlist)
return NULL;
// Py_BuildValue raises an exception if NULL is returned
py_retlist = PyList_New(0);
if (py_retlist == NULL) {
error = TRUE;
goto cleanup;
}
// Due to the use of global variables, ensure only 1 call
// to psutil_get_open_files() is running.
EnterCriticalSection(&PSUTIL_CRITICAL_SECTION);
do {
if (pHandleInfo != NULL) {
HeapFree(GetProcessHeap(), 0, pHandleInfo);
pHandleInfo = NULL;
}
if (psutil_enum_handles(&handlesList) != 0)
goto error;
// NtQuerySystemInformation won't give us the correct buffer size,
// so we guess by doubling the buffer size.
dwInfoSize *= 2;
pHandleInfo = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwInfoSize);
if (pHandleInfo == NULL) {
PyErr_NoMemory();
error = TRUE;
goto cleanup;
}
} while ((status = psutil_NtQuerySystemInformation(
SystemExtendedHandleInformation,
pHandleInfo,
dwInfoSize,
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
if (! NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status, "NtQuerySystemInformation(SystemExtendedHandleInformation)");
error = TRUE;
goto cleanup;
}
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
hHandle = &pHandleInfo->Handles[i];
// Check if this hHandle belongs to the PID the user specified.
if (hHandle->UniqueProcessId != (ULONG_PTR)dwPid)
goto loop_cleanup;
if (!DuplicateHandle(hProcess,
(HANDLE)hHandle->HandleValue,
GetCurrentProcess(),
&hFile,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
for (i = 0; i < handlesList->NumberOfHandles; i++) {
hHandle = &handlesList->Handles[i];
if ((ULONG_PTR)hHandle->UniqueProcessId != dwPid)
continue;
if (! DuplicateHandle(
hProcess,
hHandle->HandleValue,
GetCurrentProcess(),
&hFile,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
{
/*
printf("[%d] DuplicateHandle (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
goto loop_cleanup;
// Will fail if not a regular file; just skip it.
continue;
}
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMap == NULL) {
/*
printf("[%d] CreateFileMapping (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
goto loop_cleanup;
// This will set *globalFileName* global variable.
if (psutil_threaded_get_filename(hFile) != 0)
goto error;
if (globalFileName->Length > 0) {
py_path = PyUnicode_FromWideChar(globalFileName->Buffer,
wcslen(globalFileName->Buffer));
if (! py_path)
goto error;
if (PyList_Append(py_retlist, py_path))
goto error;
Py_CLEAR(py_path); // also sets to NULL
}
pMem = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 1);
if (pMem == NULL) {
/*
printf("[%d] MapViewOfFile (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
goto loop_cleanup;
// Loop cleanup section.
if (globalFileName != NULL) {
FREE(globalFileName);
globalFileName = NULL;
}
dwSize = GetMappedFileName(
GetCurrentProcess(), pMem, (LPSTR)pszFilename, MAX_PATH);
if (dwSize == 0) {
/*
printf("[%d] GetMappedFileName (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
goto loop_cleanup;
}
pszFilename[dwSize] = '\0';
/*
printf("[%d] Filename (%#x) %#d bytes: %S\n",
dwPid,
hHandle->HandleValue,
dwSize,
pszFilename);
*/
py_path = PyUnicode_FromWideChar(pszFilename, dwSize);
if (py_path == NULL) {
/*
printf("[%d] PyUnicode_FromStringAndSize (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
if (PyList_Append(py_retlist, py_path)) {
/*
printf("[%d] PyList_Append (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
loop_cleanup:
Py_XDECREF(py_path);
py_path = NULL;
if (pMem != NULL)
UnmapViewOfFile(pMem);
pMem = NULL;
if (hMap != NULL)
CloseHandle(hMap);
hMap = NULL;
if (hFile != NULL)
CloseHandle(hFile);
CloseHandle(hFile);
hFile = NULL;
dwSize = 0;
}
cleanup:
if (pMem != NULL)
UnmapViewOfFile(pMem);
pMem = NULL;
goto exit;
if (hMap != NULL)
CloseHandle(hMap);
hMap = NULL;
error:
Py_XDECREF(py_retlist);
errorOccurred = TRUE;
goto exit;
exit:
if (hFile != NULL)
CloseHandle(hFile);
hFile = NULL;
if (pHandleInfo != NULL)
HeapFree(GetProcessHeap(), 0, pHandleInfo);
pHandleInfo = NULL;
if (error) {
Py_XDECREF(py_retlist);
py_retlist = NULL;
if (globalFileName != NULL) {
FREE(globalFileName);
globalFileName = NULL;
}
if (py_path != NULL)
Py_DECREF(py_path);
if (handlesList != NULL)
FREE(handlesList);
LeaveCriticalSection(&PSUTIL_CRITICAL_SECTION);
if (errorOccurred == TRUE)
return NULL;
return py_retlist;
}
/*
* The public function.
*/
PyObject *
psutil_get_open_files(long dwPid, HANDLE hProcess) {
// Threaded version only works for Vista+
if (PSUTIL_WINVER >= PSUTIL_WINDOWS_VISTA)
return psutil_get_open_files_ntqueryobject(dwPid, hProcess);
else
return psutil_get_open_files_getmappedfilename(dwPid, hProcess);
}

Просмотреть файл

@ -7,4 +7,4 @@
#include <Python.h>
#include <windows.h>
PyObject* psutil_get_open_files(long pid, HANDLE processHandle);
PyObject* psutil_get_open_files(DWORD pid, HANDLE hProcess);

Просмотреть файл

@ -9,408 +9,26 @@
#include <Python.h>
#include <windows.h>
#include <Psapi.h>
#include <tlhelp32.h>
#include "ntextapi.h"
#include "global.h"
#include "security.h"
#include "process_info.h"
#include "../../_psutil_common.h"
#include "process_info.h"
#include "process_utils.h"
// ====================================================================
// Helper structures to access the memory correctly.
// Some of these might also be defined in the winternl.h header file
// but unfortunately not in a usable way.
// ====================================================================
// https://msdn.microsoft.com/en-us/library/aa813706(v=vs.85).aspx
#ifdef _WIN64
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[21];
PVOID LoaderData;
PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters;
/* More fields ... */
} PEB_;
#else
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PVOID Ldr;
PRTL_USER_PROCESS_PARAMETERS_ ProcessParameters;
/* More fields ... */
} PEB_;
#endif
#ifdef _WIN64
/* When we are a 64 bit process accessing a 32 bit (WoW64) process we need to
use the 32 bit structure layout. */
typedef struct {
USHORT Length;
USHORT MaxLength;
DWORD Buffer;
} UNICODE_STRING32;
typedef struct {
BYTE Reserved1[16];
DWORD Reserved2[5];
UNICODE_STRING32 CurrentDirectoryPath;
DWORD CurrentDirectoryHandle;
UNICODE_STRING32 DllPath;
UNICODE_STRING32 ImagePathName;
UNICODE_STRING32 CommandLine;
DWORD env;
} RTL_USER_PROCESS_PARAMETERS32;
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
DWORD Reserved3[2];
DWORD Ldr;
DWORD ProcessParameters;
/* More fields ... */
} PEB32;
#else
/* When we are a 32 bit (WoW64) process accessing a 64 bit process we need to
use the 64 bit structure layout and a special function to read its memory.
*/
typedef NTSTATUS (NTAPI *_NtWow64ReadVirtualMemory64)(
#ifndef _WIN64
typedef NTSTATUS (NTAPI *__NtQueryInformationProcess)(
HANDLE ProcessHandle,
PVOID64 BaseAddress,
PVOID Buffer,
ULONG64 Size,
PULONG64 NumberOfBytesRead);
typedef struct {
PVOID Reserved1[2];
PVOID64 PebBaseAddress;
PVOID Reserved2[4];
PVOID UniqueProcessId[2];
PVOID Reserved3[2];
} PROCESS_BASIC_INFORMATION64;
typedef struct {
USHORT Length;
USHORT MaxLength;
PVOID64 Buffer;
} UNICODE_STRING64;
typedef struct {
BYTE Reserved1[16];
PVOID64 Reserved2[5];
UNICODE_STRING64 CurrentDirectoryPath;
PVOID64 CurrentDirectoryHandle;
UNICODE_STRING64 DllPath;
UNICODE_STRING64 ImagePathName;
UNICODE_STRING64 CommandLine;
PVOID64 env;
} RTL_USER_PROCESS_PARAMETERS64;
typedef struct {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[21];
PVOID64 LoaderData;
PVOID64 ProcessParameters;
/* More fields ... */
} PEB64;
DWORD ProcessInformationClass,
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength);
#endif
#define PSUTIL_FIRST_PROCESS(Processes) ( \
(PSYSTEM_PROCESS_INFORMATION)(Processes))
#define PSUTIL_NEXT_PROCESS(Process) ( \
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
(PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : NULL)
// ====================================================================
// Process and PIDs utiilties.
// ====================================================================
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
/*
* Return 1 if PID exists, 0 if not, -1 on error.
* Given a pointer into a process's memory, figure out how much
* data can be read from it.
*/
int
psutil_pid_in_pids(DWORD pid) {
DWORD *proclist = NULL;
DWORD numberOfReturnedPIDs;
DWORD i;
proclist = psutil_get_pids(&numberOfReturnedPIDs);
if (proclist == NULL)
return -1;
for (i = 0; i < numberOfReturnedPIDs; i++) {
if (proclist[i] == pid) {
free(proclist);
return 1;
}
}
free(proclist);
return 0;
}
/*
* Given a process HANDLE checks whether it's actually running.
* Returns:
* - 1: running
* - 0: not running
* - -1: WindowsError
* - -2: AssertionError
*/
int
psutil_is_phandle_running(HANDLE hProcess, DWORD pid) {
DWORD processExitCode = 0;
if (hProcess == NULL) {
if (GetLastError() == ERROR_INVALID_PARAMETER) {
// Yeah, this is the actual error code in case of
// "no such process".
if (! psutil_assert_pid_not_exists(
pid, "iphr: OpenProcess() -> ERROR_INVALID_PARAMETER")) {
return -2;
}
return 0;
}
return -1;
}
if (GetExitCodeProcess(hProcess, &processExitCode)) {
// XXX - maybe STILL_ACTIVE is not fully reliable as per:
// http://stackoverflow.com/questions/1591342/#comment47830782_1591379
if (processExitCode == STILL_ACTIVE) {
if (! psutil_assert_pid_exists(
pid, "iphr: GetExitCodeProcess() -> STILL_ACTIVE")) {
return -2;
}
return 1;
}
else {
// We can't be sure so we look into pids.
if (psutil_pid_in_pids(pid) == 1) {
return 1;
}
else {
CloseHandle(hProcess);
return 0;
}
}
}
CloseHandle(hProcess);
if (! psutil_assert_pid_not_exists( pid, "iphr: exit fun")) {
return -2;
}
return -1;
}
/*
* Given a process HANDLE checks whether it's actually running and if
* it does return it, else return NULL with the proper Python exception
* set.
*/
HANDLE
psutil_check_phandle(HANDLE hProcess, DWORD pid) {
int ret = psutil_is_phandle_running(hProcess, pid);
if (ret == 1) {
return hProcess;
}
else if (ret == 0) {
return NoSuchProcess("");
}
else if (ret == -1) {
if (GetLastError() == ERROR_ACCESS_DENIED)
return PyErr_SetFromWindowsErr(0);
else
return PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
}
else {
return NULL;
}
}
/*
* A wrapper around OpenProcess setting NSP exception if process
* no longer exists.
* "pid" is the process pid, "dwDesiredAccess" is the first argument
* exptected by OpenProcess.
* Return a process handle or NULL.
*/
HANDLE
psutil_handle_from_pid(DWORD pid, DWORD access) {
HANDLE hProcess;
if (pid == 0) {
// otherwise we'd get NoSuchProcess
return AccessDenied("");
}
// needed for GetExitCodeProcess
access |= PROCESS_QUERY_LIMITED_INFORMATION;
hProcess = OpenProcess(access, FALSE, pid);
return psutil_check_phandle(hProcess, pid);
}
DWORD *
psutil_get_pids(DWORD *numberOfReturnedPIDs) {
// Win32 SDK says the only way to know if our process array
// wasn't large enough is to check the returned size and make
// sure that it doesn't match the size of the array.
// If it does we allocate a larger array and try again
// Stores the actual array
DWORD *procArray = NULL;
DWORD procArrayByteSz;
int procArraySz = 0;
// Stores the byte size of the returned array from enumprocesses
DWORD enumReturnSz = 0;
do {
procArraySz += 1024;
if (procArray != NULL)
free(procArray);
procArrayByteSz = procArraySz * sizeof(DWORD);
procArray = malloc(procArrayByteSz);
if (procArray == NULL) {
PyErr_NoMemory();
return NULL;
}
if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) {
free(procArray);
PyErr_SetFromWindowsErr(0);
return NULL;
}
} while (enumReturnSz == procArraySz * sizeof(DWORD));
// The number of elements is the returned size / size of each element
*numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
return procArray;
}
int
psutil_assert_pid_exists(DWORD pid, char *err) {
if (PSUTIL_TESTING) {
if (psutil_pid_in_pids(pid) == 0) {
PyErr_SetString(PyExc_AssertionError, err);
return 0;
}
}
return 1;
}
int
psutil_assert_pid_not_exists(DWORD pid, char *err) {
if (PSUTIL_TESTING) {
if (psutil_pid_in_pids(pid) == 1) {
PyErr_SetString(PyExc_AssertionError, err);
return 0;
}
}
return 1;
}
/*
/* Check for PID existance by using OpenProcess() + GetExitCodeProcess.
/* Returns:
* 1: pid exists
* 0: it doesn't
* -1: error
*/
int
psutil_pid_is_running(DWORD pid) {
HANDLE hProcess;
DWORD exitCode;
DWORD err;
// Special case for PID 0 System Idle Process
if (pid == 0)
return 1;
if (pid < 0)
return 0;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
if (NULL == hProcess) {
err = GetLastError();
// Yeah, this is the actual error code in case of "no such process".
if (err == ERROR_INVALID_PARAMETER) {
if (! psutil_assert_pid_not_exists(
pid, "pir: OpenProcess() -> INVALID_PARAMETER")) {
return -1;
}
return 0;
}
// Access denied obviously means there's a process to deny access to.
else if (err == ERROR_ACCESS_DENIED) {
if (! psutil_assert_pid_exists(
pid, "pir: OpenProcess() ACCESS_DENIED")) {
return -1;
}
return 1;
}
// Be strict and raise an exception; the caller is supposed
// to take -1 into account.
else {
PyErr_SetFromOSErrnoWithSyscall("OpenProcess(PROCESS_VM_READ)");
return -1;
}
}
if (GetExitCodeProcess(hProcess, &exitCode)) {
CloseHandle(hProcess);
// XXX - maybe STILL_ACTIVE is not fully reliable as per:
// http://stackoverflow.com/questions/1591342/#comment47830782_1591379
if (exitCode == STILL_ACTIVE) {
if (! psutil_assert_pid_exists(
pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) {
return -1;
}
return 1;
}
// We can't be sure so we look into pids.
else {
return psutil_pid_in_pids(pid);
}
}
else {
err = GetLastError();
CloseHandle(hProcess);
// Same as for OpenProcess, assume access denied means there's
// a process to deny access to.
if (err == ERROR_ACCESS_DENIED) {
if (! psutil_assert_pid_exists(
pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) {
return -1;
}
return 1;
}
else {
PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess");
return -1;
}
}
}
/* Given a pointer into a process's memory, figure out how much data can be
* read from it. */
static int
psutil_get_process_region_size(HANDLE hProcess, LPCVOID src, SIZE_T *psize) {
MEMORY_BASIC_INFORMATION info;
@ -431,14 +49,16 @@ enum psutil_process_data_kind {
KIND_ENVIRON,
};
/* Get data from the process with the given pid. The data is returned in the
pdata output member as a nul terminated string which must be freed on
success.
On success 0 is returned. On error the output parameter is not touched, -1
is returned, and an appropriate Python exception is set. */
/*
* Get data from the process with the given pid. The data is returned
* in the pdata output member as a nul terminated string which must be
* freed on success.
* On success 0 is returned. On error the output parameter is not touched,
* -1 is returned, and an appropriate Python exception is set.
*/
static int
psutil_get_process_data(long pid,
psutil_get_process_data(DWORD pid,
enum psutil_process_data_kind kind,
WCHAR **pdata,
SIZE_T *psize) {
@ -466,14 +86,13 @@ psutil_get_process_data(long pid,
http://stackoverflow.com/a/14012919
http://www.drdobbs.com/embracing-64-bit-windows/184401966
*/
_NtQueryInformationProcess NtQueryInformationProcess = NULL;
SIZE_T size = 0;
#ifndef _WIN64
static _NtQueryInformationProcess NtWow64QueryInformationProcess64 = NULL;
static __NtQueryInformationProcess NtWow64QueryInformationProcess64 = NULL;
static _NtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = NULL;
#endif
HANDLE hProcess = NULL;
LPCVOID src;
SIZE_T size;
WCHAR *buffer = NULL;
#ifdef _WIN64
LPVOID ppeb32 = NULL;
@ -492,7 +111,7 @@ psutil_get_process_data(long pid,
#ifdef _WIN64
/* 64 bit case. Check if the target is a 32 bit process running in WoW64
* mode. */
status = psutil_NtQueryInformationProcess(
status = NtQueryInformationProcess(
hProcess,
ProcessWow64Information,
&ppeb32,
@ -512,18 +131,22 @@ psutil_get_process_data(long pid,
// read PEB
if (!ReadProcessMemory(hProcess, ppeb32, &peb32, sizeof(peb32), NULL)) {
PyErr_SetFromOSErrnoWithSyscall("ReadProcessMemory");
// May fail with ERROR_PARTIAL_COPY, see:
// https://github.com/giampaolo/psutil/issues/875
PyErr_SetFromWindowsErr(0);
goto error;
}
// read process parameters
if (!ReadProcessMemory(hProcess,
UlongToPtr(peb32.ProcessParameters),
&procParameters32,
sizeof(procParameters32),
NULL)) {
PyErr_SetFromOSErrnoWithSyscall(
"ReadProcessMemory(ProcessParameters)");
UlongToPtr(peb32.ProcessParameters),
&procParameters32,
sizeof(procParameters32),
NULL))
{
// May fail with ERROR_PARTIAL_COPY, see:
// https://github.com/giampaolo/psutil/issues/875
PyErr_SetFromWindowsErr(0);
goto error;
}
@ -576,41 +199,44 @@ psutil_get_process_data(long pid,
}
}
if (! NT_SUCCESS(
NtWow64QueryInformationProcess64(
status = NtWow64QueryInformationProcess64(
hProcess,
ProcessBasicInformation,
&pbi64,
sizeof(pbi64),
NULL)))
{
PyErr_SetFromOSErrnoWithSyscall(
"NtWow64QueryInformationProcess64(ProcessBasicInformation)");
NULL);
if (!NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status,
"NtWow64QueryInformationProcess64(ProcessBasicInformation)"
);
goto error;
}
// read peb
if (! NT_SUCCESS(NtWow64ReadVirtualMemory64(
hProcess,
pbi64.PebBaseAddress,
&peb64,
sizeof(peb64),
NULL)))
{
PyErr_SetFromOSErrnoWithSyscall("NtWow64ReadVirtualMemory64");
status = NtWow64ReadVirtualMemory64(
hProcess,
pbi64.PebBaseAddress,
&peb64,
sizeof(peb64),
NULL);
if (!NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64");
goto error;
}
// read process parameters
if (! NT_SUCCESS(NtWow64ReadVirtualMemory64(
status = NtWow64ReadVirtualMemory64(
hProcess,
peb64.ProcessParameters,
&procParameters64,
sizeof(procParameters64),
NULL)))
{
PyErr_SetFromOSErrnoWithSyscall(
"NtWow64ReadVirtualMemory64(ProcessParameters)");
NULL);
if (!NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(
status,
"NtWow64ReadVirtualMemory64(ProcessParameters)"
);
goto error;
}
@ -635,7 +261,7 @@ psutil_get_process_data(long pid,
PEB_ peb;
RTL_USER_PROCESS_PARAMETERS_ procParameters;
status = psutil_NtQueryInformationProcess(
status = NtQueryInformationProcess(
hProcess,
ProcessBasicInformation,
&pbi,
@ -654,8 +280,11 @@ psutil_get_process_data(long pid,
pbi.PebBaseAddress,
&peb,
sizeof(peb),
NULL)) {
PyErr_SetFromOSErrnoWithSyscall("ReadProcessMemory");
NULL))
{
// May fail with ERROR_PARTIAL_COPY, see:
// https://github.com/giampaolo/psutil/issues/875
PyErr_SetFromWindowsErr(0);
goto error;
}
@ -664,9 +293,11 @@ psutil_get_process_data(long pid,
peb.ProcessParameters,
&procParameters,
sizeof(procParameters),
NULL)) {
PyErr_SetFromOSErrnoWithSyscall(
"ReadProcessMemory(ProcessParameters)");
NULL))
{
// May fail with ERROR_PARTIAL_COPY, see:
// https://github.com/giampaolo/psutil/issues/875
PyErr_SetFromWindowsErr(0);
goto error;
}
@ -705,20 +336,22 @@ psutil_get_process_data(long pid,
#ifndef _WIN64
if (weAreWow64 && !theyAreWow64) {
if (! NT_SUCCESS(NtWow64ReadVirtualMemory64(
status = NtWow64ReadVirtualMemory64(
hProcess,
src64,
buffer,
size,
NULL)))
{
PyErr_SetFromOSErrnoWithSyscall("NtWow64ReadVirtualMemory64");
NULL);
if (!NT_SUCCESS(status)) {
psutil_SetFromNTStatusErr(status, "NtWow64ReadVirtualMemory64");
goto error;
}
} else
#endif
if (!ReadProcessMemory(hProcess, src, buffer, size, NULL)) {
PyErr_SetFromOSErrnoWithSyscall("ReadProcessMemory");
// May fail with ERROR_PARTIAL_COPY, see:
// https://github.com/giampaolo/psutil/issues/875
PyErr_SetFromWindowsErr(0);
goto error;
}
@ -744,8 +377,8 @@ error:
* AccessDenied. Requires Windows 8.1+.
*/
static int
psutil_cmdline_query_proc(long pid, WCHAR **pdata, SIZE_T *psize) {
HANDLE hProcess;
psutil_cmdline_query_proc(DWORD pid, WCHAR **pdata, SIZE_T *psize) {
HANDLE hProcess = NULL;
ULONG bufLen = 0;
NTSTATUS status;
char * buffer = NULL;
@ -765,16 +398,15 @@ psutil_cmdline_query_proc(long pid, WCHAR **pdata, SIZE_T *psize) {
goto error;
// get the right buf size
status = psutil_NtQueryInformationProcess(
status = NtQueryInformationProcess(
hProcess,
ProcessCommandLineInformation,
NULL,
0,
&bufLen);
// 0xC0000225 == STATUS_NOT_FOUND, see:
// https://github.com/giampaolo/psutil/issues/1501
if (status == 0xC0000225) {
if (status == STATUS_NOT_FOUND) {
AccessDenied("NtQueryInformationProcess(ProcessBasicInformation) -> "
"STATUS_NOT_FOUND translated into PermissionError");
goto error;
@ -796,7 +428,7 @@ psutil_cmdline_query_proc(long pid, WCHAR **pdata, SIZE_T *psize) {
}
// get the cmdline
status = psutil_NtQueryInformationProcess(
status = NtQueryInformationProcess(
hProcess,
ProcessCommandLineInformation,
buffer,
@ -838,7 +470,7 @@ error:
* with given pid or NULL on error.
*/
PyObject *
psutil_get_cmdline(long pid, int use_peb) {
psutil_get_cmdline(DWORD pid, int use_peb) {
PyObject *ret = NULL;
WCHAR *data = NULL;
SIZE_T size;
@ -899,7 +531,7 @@ out:
PyObject *
psutil_get_cwd(long pid) {
psutil_get_cwd(DWORD pid) {
PyObject *ret = NULL;
WCHAR *data = NULL;
SIZE_T size;
@ -923,7 +555,7 @@ out:
* process with given pid or NULL on error.
*/
PyObject *
psutil_get_environ(long pid) {
psutil_get_environ(DWORD pid) {
PyObject *ret = NULL;
WCHAR *data = NULL;
SIZE_T size;
@ -943,10 +575,11 @@ out:
/*
* Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
* fills the structure with various process information by using
* NtQuerySystemInformation.
* fills the structure with various process information in one shot
* by using NtQuerySystemInformation.
* We use this as a fallback when faster functions fail with access
* denied. This is slower because it iterates over all processes.
* denied. This is slower because it iterates over all processes
* but it doesn't require any privilege (also work for PID 0).
* On success return 1, else 0 with Python exception already set.
*/
int
@ -966,7 +599,7 @@ psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
}
while (TRUE) {
status = psutil_NtQuerySystemInformation(
status = NtQuerySystemInformation(
SystemProcessInformation,
buffer,
bufferSize,
@ -997,14 +630,14 @@ psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
process = PSUTIL_FIRST_PROCESS(buffer);
do {
if (process->UniqueProcessId == (HANDLE)pid) {
if ((ULONG_PTR)process->UniqueProcessId == pid) {
*retProcess = process;
*retBuffer = buffer;
return 1;
}
} while ( (process = PSUTIL_NEXT_PROCESS(process)) );
} while ((process = PSUTIL_NEXT_PROCESS(process)));
NoSuchProcess("");
NoSuchProcess("NtQuerySystemInformation (no PID found)");
goto error;
error:
@ -1012,3 +645,89 @@ error:
free(buffer);
return 0;
}
/*
* Get various process information by using NtQuerySystemInformation.
* We use this as a fallback when faster functions fail with access
* denied. This is slower because it iterates over all processes.
* Returned tuple includes the following process info:
*
* - num_threads()
* - ctx_switches()
* - num_handles() (fallback)
* - cpu_times() (fallback)
* - create_time() (fallback)
* - io_counters() (fallback)
* - memory_info() (fallback)
*/
PyObject *
psutil_proc_info(PyObject *self, PyObject *args) {
DWORD pid;
PSYSTEM_PROCESS_INFORMATION process;
PVOID buffer;
ULONG i;
ULONG ctx_switches = 0;
double user_time;
double kernel_time;
double create_time;
PyObject *py_retlist;
if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (! psutil_get_proc_info(pid, &process, &buffer))
return NULL;
for (i = 0; i < process->NumberOfThreads; i++)
ctx_switches += process->Threads[i].ContextSwitches;
user_time = (double)process->UserTime.HighPart * HI_T + \
(double)process->UserTime.LowPart * LO_T;
kernel_time = (double)process->KernelTime.HighPart * HI_T + \
(double)process->KernelTime.LowPart * LO_T;
// Convert the LARGE_INTEGER union to a Unix time.
// It's the best I could find by googling and borrowing code here
// and there. The time returned has a precision of 1 second.
if (0 == pid || 4 == pid) {
// the python module will translate this into BOOT_TIME later
create_time = 0;
}
else {
create_time = psutil_LargeIntegerToUnixTime(process->CreateTime);
}
py_retlist = Py_BuildValue(
#if defined(_WIN64)
"kkdddiKKKKKK" "kKKKKKKKKK",
#else
"kkdddiKKKKKK" "kIIIIIIIII",
#endif
process->HandleCount, // num handles
ctx_switches, // num ctx switches
user_time, // cpu user time
kernel_time, // cpu kernel time
create_time, // create time
(int)process->NumberOfThreads, // num threads
// IO counters
process->ReadOperationCount.QuadPart, // io rcount
process->WriteOperationCount.QuadPart, // io wcount
process->ReadTransferCount.QuadPart, // io rbytes
process->WriteTransferCount.QuadPart, // io wbytes
process->OtherOperationCount.QuadPart, // io others count
process->OtherTransferCount.QuadPart, // io others bytes
// memory
process->PageFaultCount, // num page faults
process->PeakWorkingSetSize, // peak wset
process->WorkingSetSize, // wset
process->QuotaPeakPagedPoolUsage, // peak paged pool
process->QuotaPagedPoolUsage, // paged pool
process->QuotaPeakNonPagedPoolUsage, // peak non paged pool
process->QuotaNonPagedPoolUsage, // non paged pool
process->PagefileUsage, // pagefile
process->PeakPagefileUsage, // peak pagefile
process->PrivatePageCount // private
);
free(buffer);
return py_retlist;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше