Bug 1196253 - update in-tree psutil to 3.1.1. r=gps

This commit is contained in:
Joel Maher 2015-08-20 08:03:31 -04:00
parent 221a5e5c4b
commit 3df7576e09
73 changed files with 6544 additions and 3863 deletions

View File

@ -255,9 +255,56 @@ I: 492
N: Jeff Tang
W: https://github.com/mrjefftang
I: 340, 529
I: 340, 529, 616, 653, 654
N: Yaolong Huang
E: airekans@gmail.com
W: http://airekans.github.io/
I: 530
N: Anders Chrigström
W: https://github.com/anders-chrigstrom
I: 496
N: spacewander
E: spacewanderlzx@gmail.com
I: 561
N: Sylvain Mouquet
E: sylvain.mouquet@gmail.com
I: 565
N: karthikrev
I: 568
N: Bruno Binet
E: bruno.binet@gmail.com
I: 572
N: Gabi Davar
C: Israel
W: https://github.com/mindw
I: 578, 581, 587
N: spacewanderlzx
C: Guangzhou,China
E: spacewanderlzx@gmail.com
I: 555
N: Fabian Groffen
I: 611, 618
N: desbma
W: https://github.com/desbma
C: France
I: 628
N: John Burnett
W: http://www.johnburnett.com/
C: Irvine, CA, US
I: 614
N: Árni Már Jónsson
E: Reykjavik, Iceland
E: https://github.com/arnimarj
I: 634

View File

@ -1,10 +1,143 @@
Bug tracker at https://github.com/giampaolo/psutil/issues
2.1.3 2014-09-26
================
3.1.1 - 2015-07-15
==================
**Bug fixes**
- #645: [Linux] psutil.cpu_times_percent() may produce negative results.
- #656: 'from psutil import *' does not work.
3.1.0 - 2015-07-15
==================
**Enhancements**
- #534: [Linux] disk_partitions() added support for ZFS filesystems.
- #646: continuous tests integration for Windows with
https://ci.appveyor.com/project/giampaolo/psutil.
- #647: new dev guide:
https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst
- #651: continuous code quality test integration with
https://scrutinizer-ci.com/g/giampaolo/psutil/
**Bug fixes**
- #340: [Windows] Process.open_files() no longer hangs. Instead it uses a
thred which times out and skips the file handle in case it's taking too long
to be retrieved. (patch by Jeff Tang, PR #597)
- #627: [Windows] Process.name() no longer raises AccessDenied for pids owned
by another user.
- #636: [Windows] Process.memory_info() raise AccessDenied.
- #637: [UNIX] raise exception if trying to send signal to Process PID 0 as it
will affect os.getpid()'s process group instead of PID 0.
- #639: [Linux] Process.cmdline() can be truncated.
- #640: [Linux] *connections functions may swallow errors and return an
incomplete list of connnections.
- #642: repr() of exceptions is incorrect.
- #653: [Windows] Add inet_ntop function for Windows XP to support IPv6.
- #641: [Windows] Replace deprecated string functions with safe equivalents.
3.0.1 - 2015-06-18
==================
**Bug fixes**
- #632: [Linux] better error message if cannot parse process UNIX connections.
- #634: [Linux] Proces.cmdline() does not include empty string arguments.
- #635: [UNIX] crash on module import if 'enum' package is installed on python
< 3.4.
3.0.0 - 2015-06-13
==================
**Enhancements**
- #250: new psutil.net_if_stats() returning NIC statistics (isup, duplex,
speed, MTU).
- #376: new psutil.net_if_addrs() returning all NIC addresses a-la ifconfig.
- #469: on Python >= 3.4 ``IOPRIO_CLASS_*`` and ``*_PRIORITY_CLASS`` constants
returned by psutil.Process' ionice() and nice() methods are enums instead of
plain integers.
- #581: add .gitignore. (patch by Gabi Davar)
- #582: connection constants returned by psutil.net_connections() and
psutil.Process.connections() were turned from int to enums on Python > 3.4.
- #587: Move native extension into the package.
- #589: Process.cpu_affinity() accepts any kind of iterable (set, tuple, ...),
not only lists.
- #594: all deprecated APIs were removed.
- #599: [Windows] process name() can now be determined for all processes even
when running as a limited user.
- #602: pre-commit GIT hook.
- #629: enhanced support for py.test and nose test discovery and tests run.
- #616: [Windows] Add inet_ntop function for Windows XP.
**Bug fixes**
- #428: [all UNIXes except Linux] correct handling of zombie processes;
introduced new ZombieProcess exception class.
- #512: [BSD] fix segfault in net_connections().
- #555: [Linux] psutil.users() correctly handles ":0" as an alias for
"localhost"
- #579: [Windows] Fixed open_files() for PID>64K.
- #579: [Windows] fixed many compiler warnings.
- #585: [FreeBSD] net_connections() may raise KeyError.
- #586: [FreeBSD] cpu_affinity() segfaults on set in case an invalid CPU
number is provided.
- #593: [FreeBSD] Process().memory_maps() segfaults.
- #606: Process.parent() may swallow NoSuchProcess exceptions.
- #611: [SunOS] net_io_counters has send and received swapped
- #614: [Linux]: cpu_count(logical=False) return the number of physical CPUs
instead of physical cores.
- #618: [SunOS] swap tests fail on Solaris when run as normal user
- #628: [Linux] Process.name() truncates process name in case it contains
spaces or parentheses.
2.2.1 - 2015-02-02
==================
**Bug fixes**
- #496: [Linux] fix "ValueError: ambiguos inode with multiple PIDs references"
(patch by Bruno Binet)
2.2.0 - 2015-01-06
==================
**Enhancements**
- #521: drop support for Python 2.4 and 2.5.
- #553: new examples/pstree.py script.
- #564: C extension version mismatch in case the user messed up with psutil
installation or with sys.path is now detected at import time.
- #568: New examples/pidof.py script.
- #569: [FreeBSD] add support for process CPU affinity.
**Bug fixes**
- #496: [Solaris] can't import psutil.
- #547: [UNIX] Process.username() may raise KeyError if UID can't be resolved.
- #551: [Windows] get rid of the unicode hack for net_io_counters() NIC names.
- #556: [Linux] lots of file handles were left open.
- #561: [Linux] net_connections() might skip some legitimate UNIX sockets.
(patch by spacewander)
- #565: [Windows] use proper encoding for psutil.Process.username() and
psutil.users(). (patch by Sylvain Mouquet)
- #567: [Linux] in the alternative implementation of CPU affinity PyList_Append
and Py_BuildValue return values are not checked.
- #569: [FreeBSD] fix memory leak in psutil.cpu_count(logical=False).
- #571: [Linux] Process.open_files() might swallow AccessDenied exceptions and
return an incomplete list of open files.
2.1.3 - 2014-09-26
==================
- #536: [Linux]: fix "undefined symbol: CPU_ALLOC" compilation error.

View File

@ -4,12 +4,12 @@ Installing using pip on UNIX
The easiest way to install psutil on UNIX is by using pip (but first you might
need to install python header files; see later).
First install pip:
First install pip::
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
python ez_setup.py
$ wget https://bootstrap.pypa.io/get-pip.py
$ python get-pip.py
...then run:
...then run::
$ pip install psutil
@ -22,51 +22,27 @@ Installing on Windows
Just get the right installer for your Python version and architecture from:
https://pypi.python.org/pypi/psutil/#downloads
==================================
Compiling on Windows using mingw32
==================================
First install mingw (http://www.mingw.org/) then add mingw "bin" folder to
environment PATH (NOTE: this assumes MinGW is installed in C:\MinGW):
SET PATH=C:\MinGW\bin;%PATH%
You can then compile psutil by running:
setup.py build -c mingw32
To compile and install:
setup.py build -c mingw32 install
You can also use make.bat which automatically sets the env variable for you:
make.bat build
FWIW I managed to compile psutil against all 32-bit Python versions but not
64 bit.
Since wheels installers are also available you may also use pip.
========================================
Compiling on Windows using Visual Studio
========================================
To use Visual Studio to compile psutil you must have the same version of
Visual Studio used to compile your installation of Python which is::
In order to compile psutil on Windows you'll need Visual Studio (Mingw32 is
no longer supported). You must have the same version of Visual Studio used to compile
your installation of Python, that is::
Python 2.4: VS 2003
Python 2.5: VS 2003
Python 2.6: VS 2008
Python 2.7: VS 2008
Python 3.3+: VS 2010
* Python 2.6: VS 2008
* Python 2.7: VS 2008
* Python 3.3, 3.4: VS 2010 (you can download it from `MS website <http://www.visualstudio.com/downloads/download-visual-studio-vs#d-2010-express>`_)
* Python 3.5: `VS 2015 UP <http://www.visualstudio.com/en-au/news/vs2015-preview-vs>`_
...then run:
...then run::
setup.py build
...or:
...or::
make.bat build
@ -75,24 +51,20 @@ Windows SDK and .NET Framework 3.5 SP1 to be installed first.
Once you have those run vcvars64.bat, then compile:
http://stackoverflow.com/questions/11072521/
If you do not have the right version of Visual Studio available then try using
MinGW instead.
===================
Installing on Linux
===================
gcc is required and so the python headers. They can easily be installed by
using the distro package manager. For example, on Debian amd Ubuntu:
using the distro package manager. For example, on Debian and Ubuntu::
$ sudo apt-get install gcc python-dev
...on Redhat and CentOS:
...on Redhat and CentOS::
$ sudo yum install gcc python-devel
Once done, you can build/install psutil with:
Once done, you can build/install psutil with::
$ python setup.py install
@ -104,11 +76,11 @@ Installing on OS X
OS X installation from source will require gcc which you can obtain as part of
the 'XcodeTools' installer from Apple. Then you can run the standard distutils
commands.
To build only:
To build only::
$ python setup.py build
To install and build:
To install and build::
$ python setup.py install
@ -121,11 +93,11 @@ The same compiler used to install Python must be present on the system in order
to build modules using distutils. Assuming it is installed, you can build using
the standard distutils commands.
Build only:
Build only::
$ python setup.py build
Install and build:
Install and build::
$ python setup.py install
@ -138,7 +110,7 @@ A makefile is available for both UNIX and Windows (make.bat). It provides
some automations for the tasks described above and might be preferred over
using setup.py. With it you can::
$ make install # just install
$ make install # just install (in --user mode)
$ make uninstall # uninstall (needs pip)
$ make test # run tests
$ make clean # remove installation files

View File

@ -1,3 +1,7 @@
include .coveragerc
include .git-pre-commit
include .git-pre-commit
include .gitignore
include .travis.yml
include CREDITS
include HISTORY.rst
@ -10,8 +14,9 @@ include README.rst
include setup.py
include TODO
include tox.ini
recursive-include docs *
recursive-exclude docs/_build *
recursive-include .appveyor/*
recursive-include docs *
recursive-include examples *.py
recursive-include psutil *.py *.c *.h
recursive-include test *.py README
recursive-include test *.py README*

View File

@ -16,31 +16,49 @@ clean:
rm -f `find . -type f -name \*.bak`
rm -f `find . -type f -name \*.rej`
rm -rf `find . -type d -name __pycache__`
rm -rf *.core
rm -rf *.egg-info
rm -rf *\$testfile*
rm -rf .coverage
rm -rf .tox
rm -rf build
rm -rf dist
rm -rf docs/_build
rm -rf htmlcov
build: clean
$(PYTHON) setup.py build
@# copies *.so files in ./psutil directory in order to allow
@# "import psutil" when using the interactive interpreter from within
@# this directory.
$(PYTHON) setup.py build_ext -i
# useful deps which are nice to have while developing / testing
setup-dev-env:
python -c "import urllib2; \
r = urllib2.urlopen('https://bootstrap.pypa.io/get-pip.py'); \
open('/tmp/get-pip.py', 'w').write(r.read());"
$(PYTHON) /tmp/get-pip.py --user
rm /tmp/get-pip.py
$(PYTHON) -m pip install --user --upgrade pip
$(PYTHON) -m pip install --user --upgrade \
coverage \
flake8 \
ipaddress \
ipdb \
mock==1.0.1 \
nose \
pep8 \
pyflakes \
sphinx \
sphinx-pypi-upload \
unittest2 \
install: build
if test $(PYTHON) = python2.4; then \
$(PYTHON) setup.py install; \
elif test $(PYTHON) = python2.5; then \
$(PYTHON) setup.py install; \
else \
$(PYTHON) setup.py install --user; \
fi
$(PYTHON) setup.py install --user
uninstall:
if test $(PYTHON) = python2.4; then \
pip-2.4 uninstall -y -v psutil; \
else \
cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
fi
cd ..; $(PYTHON) -m pip uninstall -y -v psutil
test: install
$(PYTHON) $(TSCRIPT)
@ -52,27 +70,36 @@ test-system: install
$(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
test-memleaks: install
$(PYTHON) -m unittest -v test.test_memory_leaks
$(PYTHON) test/test_memory_leaks.py
# Run a specific test by name; e.g. "make test-by-name disk_" will run
# all test methods containing "disk_" in their name.
# Requires "pip install nose".
test-by-name:
@$(PYTHON) -m nose test/test_psutil.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
test-by-name: install
@$(PYTHON) -m nose test/test_psutil.py test/_* --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
# Same as above but for test_memory_leaks.py script.
test-memleaks-by-name: install
@$(PYTHON) -m nose test/test_memory_leaks.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS))
coverage: install
# Note: coverage options are controlled by .coveragerc file
rm -rf .coverage htmlcov
$(PYTHON) -m coverage run $(TSCRIPT)
$(PYTHON) -m coverage report
@echo "writing results to htmlcov/index.html"
$(PYTHON) -m coverage html
$(PYTHON) -m webbrowser -t htmlcov/index.html
# requires "pip install pep8"
pep8:
@git ls-files | grep \\.py$ | xargs pep8
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m pep8
# requires "pip install pyflakes"
pyflakes:
@export PYFLAKES_NODOCTEST=1 && \
git ls-files | grep \\.py$ | xargs pyflakes
git ls-files | grep \\.py$ | xargs $(PYTHON) -m pyflakes
# requires "pip install flake8"
flake8:
@git ls-files | grep \\.py$ | xargs flake8
@git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8
# Upload source tarball on https://pypi.python.org/pypi/psutil.
upload-src: clean
@ -88,3 +115,8 @@ upload-doc:
git-tag-release:
git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD`
echo "done; now run 'git push --follow-tags' to push the new tag on the remote repo"
# install GIT pre-commit hook
install-git-hooks:
ln -sf ../../.git-pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

View File

@ -1,26 +1,42 @@
Metadata-Version: 1.1
Name: psutil
Version: 2.1.3
Version: 3.1.1
Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python.
Home-page: https://github.com/giampaolo/psutil
Author: Giampaolo Rodola
Author-email: g.rodola <at> gmail <dot> com
License: BSD
Description: .. image:: https://pypip.in/d/psutil/badge.png
:target: https://crate.io/packages/psutil/
:alt: Download this month
.. image:: https://pypip.in/v/psutil/badge.png
:target: https://pypi.python.org/pypi/psutil/
:alt: Latest version
.. image:: https://pypip.in/license/psutil/badge.png
:target: https://pypi.python.org/pypi/psutil/
:alt: License
Description: .. image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pypi.python.org/pypi/psutil#downloads
:alt: Downloads this month
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
:target: https://travis-ci.org/giampaolo/psutil
:alt: Travis
:alt: Linux tests (Travis)
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://img.shields.io/pypi/v/psutil.svg
: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/scrutinizer/g/giampaolo/psutil.svg
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
:alt: Code quality (scrutinizer-ci.com)
.. image:: https://img.shields.io/pypi/l/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
:alt: License
===========
Quick links
@ -28,9 +44,11 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
- `Home page <https://github.com/giampaolo/psutil>`_
- `Documentation <http://pythonhosted.org/psutil/>`_
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `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>`_
=======
@ -45,8 +63,9 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
**64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
also known to work.
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
`PyPy <http://pypy.org/>`__ is also known to work.
====================
Example applications
@ -67,8 +86,8 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
See also:
* https://github.com/nicolargo/glances
* https://github.com/google/grr
* https://github.com/Jahaja/psdash
* https://code.google.com/p/grr/
==============
Example usages
@ -117,9 +136,9 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
.. code-block:: python
>>> psutil.virtual_memory()
svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
>>> psutil.swap_memory()
sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
>>>
Disks
@ -148,11 +167,23 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
'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()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 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'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
>>>
>>> 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)}
Other system info
=================
@ -218,7 +249,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
>>>
>>> p.memory_info()
pmem(rss=7471104, vms=68513792)
>>> p.ext_memory_info()
>>> p.memory_info_ex()
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
@ -235,10 +266,10 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
>>>
>>> p.connections()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
>>>
>>> p.num_threads()
4
@ -259,7 +290,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
>>>
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
>>> p.ionice()
pionice(ioclass=3, value=0)
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)
@ -327,6 +358,12 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
Timeline
========
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
@ -356,7 +393,7 @@ Description: .. image:: https://pypip.in/d/psutil/badge.png
- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,monitoring,ulimit,prlimit
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
Platform: Platform Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
@ -375,8 +412,6 @@ Classifier: Operating System :: POSIX :: SunOS/Solaris
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.4
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3

View File

@ -1,18 +1,34 @@
.. image:: https://pypip.in/d/psutil/badge.png
:target: https://crate.io/packages/psutil/
:alt: Download this month
.. image:: https://pypip.in/v/psutil/badge.png
:target: https://pypi.python.org/pypi/psutil/
:alt: Latest version
.. image:: https://pypip.in/license/psutil/badge.png
:target: https://pypi.python.org/pypi/psutil/
:alt: License
.. image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pypi.python.org/pypi/psutil#downloads
:alt: Downloads this month
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
:target: https://travis-ci.org/giampaolo/psutil
:alt: Travis
:alt: Linux tests (Travis)
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://img.shields.io/pypi/v/psutil.svg
: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/scrutinizer/g/giampaolo/psutil.svg
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
:alt: Code quality (scrutinizer-ci.com)
.. image:: https://img.shields.io/pypi/l/psutil.svg
:target: https://pypi.python.org/pypi/psutil/
:alt: License
===========
Quick links
@ -20,9 +36,11 @@ Quick links
- `Home page <https://github.com/giampaolo/psutil>`_
- `Documentation <http://pythonhosted.org/psutil/>`_
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `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>`_
=======
@ -37,8 +55,9 @@ running processes**. It implements many functionalities offered by command line
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
**64-bit** architectures, with Python versions from **2.4 to 3.4**. PyPy is
also known to work.
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
`PyPy <http://pypy.org/>`__ is also known to work.
====================
Example applications
@ -59,8 +78,8 @@ Example applications
See also:
* https://github.com/nicolargo/glances
* https://github.com/google/grr
* https://github.com/Jahaja/psdash
* https://code.google.com/p/grr/
==============
Example usages
@ -109,9 +128,9 @@ Memory
.. code-block:: python
>>> psutil.virtual_memory()
svmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
>>> psutil.swap_memory()
sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
>>>
Disks
@ -140,11 +159,23 @@ Network
'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()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 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'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
>>>
>>> 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)}
Other system info
=================
@ -210,7 +241,7 @@ Process management
>>>
>>> p.memory_info()
pmem(rss=7471104, vms=68513792)
>>> p.ext_memory_info()
>>> p.memory_info_ex()
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
@ -227,10 +258,10 @@ Process management
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
>>>
>>> p.connections()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
>>>
>>> p.num_threads()
4
@ -251,7 +282,7 @@ Process management
>>>
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only)
>>> p.ionice()
pionice(ioclass=3, value=0)
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)
@ -319,6 +350,12 @@ http://groups.google.com/group/psutil/
Timeline
========
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_

View File

@ -9,22 +9,29 @@ https://github.com/giampaolo/psutil/issues
HIGHER PRIORITY
===============
* #250: net ifaces speed.
* #376: ifconfig functionalities aka psutil.net_ifaces (could be merged
with #250)
* OpenBSD support.
* #371: CPU temperature (apparently OSX and Linux only; on Linux it requires
lm-sensors lib).
* #269: expose network ifaces RX/TW queues.
* #269: expose network ifaces RX/TW queues. This should probably go into
net_if_stats(). Figure out on what platforms this is supported:
Linux: yes
Others: ?
* Process.threads(): thread names
* Process.threads(): thread names; patch for OSX available at:
https://code.google.com/p/plcrashreporter/issues/detail?id=65
* Asynchronous psutil.Popen (see http://bugs.python.org/issue1191964)
* (Windows) fall back on using WMIC for Process methods returning AccessDenied
* #613: thread names.
* #604: emulate os.getloadavg() on Windows
* #269: NIC rx/tx queue.
LOWER PRIORITY
==============
@ -39,11 +46,6 @@ LOWER PRIORITY
* AIX support?
* examples/pidof.py (same as 'pidof' cli tool)
* examples/pstree.py (same as 'pstree' cli tool)
* threads() should also return thread names in order to implement it
* examples/taskmgr-gui.py (using tk).
* system-wide number of open file descriptors:
@ -55,10 +57,7 @@ LOWER PRIORITY
* #357: what CPU a process is on.
* thread names:
* https://code.google.com/p/plcrashreporter/issues/detail?id=65
* Doc / wiki which compares similarities between UNIX cli tools and psutil.
* Doc / wiki which compares similarities between UNIX cli tools and psutil.
Example:
df -a -> psutil.disk_partitions
lsof -> psutil.Process.open_files() and psutil.Process.open_connections()
@ -70,7 +69,13 @@ LOWER PRIORITY
DEBATABLE
=========
* support wheels? http://pythonwheels.com/
* psutil.proc_tree() something which obtains a {pid:ppid, ...} dict for
all running processes in one shot. This can be factored out from
Process.children() and exposed as a first class function.
PROS: on Windows we can take advantage of _psutil_windows.ppid_map()
which is faster than iterating over all pids and calling ppid().
CONS: examples/pstree.py shows this can be easily done in the user code
so maybe it's not worth the addition.
* advanced cmdline interface exposing the whole API and providing different
kind of outputs (e.g. pprinted, colorized, json).
@ -91,10 +96,18 @@ DEBATABLE
Also, we can probably reimplement wait_pid() on POSIX which is currently
implemented as a busy-loop.
* Certain systems (XXX figure out which ones exactly) provide CPU times about
process children. On those systems Process.cpu_times() might return
a (user, system, user_children, system_children) ntuple.
Also, os.times() provides 'elapsed' times as well.
* Certain systems provide CPU times about process children. On those systems
Process.cpu_times() might return a (user, system, user_children,
system_children) ntuple.
* Linux: /proc/{PID}/stat
* Solaris: pr_cutime and pr_cstime
* FreeBSD: none
* OSX: none
* Windows: none
* ...also, os.times() provides 'elapsed' times as well.
* ...also Linux provides guest_time and cguest_time.
* Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that:
- NoSuchProcess inherits from ProcessLookupError
@ -130,6 +143,10 @@ DEBATABLE
* round Process.memory_percent() result?
* #550: number of threads per core.
* Have psutil.Process().cpu_affinity([]) be an alias for "all CPUs"?
COMPATIBILITY BREAKAGE
======================
@ -147,4 +164,4 @@ Removals (will likely happen in 2.2):
REJECTED IDEAS
==============
STUB
STUB

View File

@ -14,29 +14,17 @@
import datetime
import os
import sys
if sys.version_info >= (3, ):
def u(s):
return s
else:
def u(s):
if not isinstance(s, unicode): # NOQA
s = unicode(s, "unicode_escape") # NOQA
return s
PROJECT_NAME = u("psutil")
AUTHOR = u("Giampaolo Rodola'")
PROJECT_NAME = "psutil"
AUTHOR = "Giampaolo Rodola'"
THIS_YEAR = str(datetime.datetime.now().year)
HERE = os.path.abspath(os.path.dirname(__file__))
def get_version():
INIT = os.path.abspath(os.path.join(HERE, '../psutil/__init__.py'))
f = open(INIT, 'r')
try:
with open(INIT, 'r') as f:
for line in f:
if line.startswith('__version__'):
ret = eval(line.strip().split(' = ')[1])
@ -46,8 +34,6 @@ def get_version():
return ret
else:
raise ValueError("couldn't find version string")
finally:
f.close()
VERSION = get_version()
@ -77,7 +63,7 @@ master_doc = 'index'
# General information about the project.
project = PROJECT_NAME
copyright = u('2009-%s, %s' % (THIS_YEAR, AUTHOR))
copyright = '2009-%s, %s' % (THIS_YEAR, AUTHOR)
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -223,7 +209,7 @@ htmlhelp_basename = '%s-doc' % PROJECT_NAME
# [howto/manual]).
latex_documents = [
('index', '%s.tex' % PROJECT_NAME,
u('%s documentation') % PROJECT_NAME, AUTHOR),
'%s documentation' % PROJECT_NAME, AUTHOR),
]
# The name of an image file (relative to this directory) to place at
@ -255,7 +241,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', PROJECT_NAME, u('%s documentation') % PROJECT_NAME, [AUTHOR], 1)
('index', PROJECT_NAME, '%s documentation' % PROJECT_NAME, [AUTHOR], 1)
]
# If true, show URL addresses after external links.

View File

@ -18,8 +18,10 @@ Quick links
* `Home page <https://github.com/giampaolo/psutil>`__
* `Blog <http://grodola.blogspot.com/search/label/psutil>`__
* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__
* `Forum <http://groups.google.com/group/psutil/topics>`__
* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__
* `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
* `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_
* `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`__
About
@ -38,8 +40,8 @@ From project's home page:
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap*.
It currently supports **Linux, Windows, OSX, FreeBSD** and **Sun Solaris**,
both **32-bit** and **64-bit** architectures, with Python versions from
**2.4** to **3.4**.
`Pypy <http://pypy.org/>`__ is also known to work.
**2.6 to 3.4** (users of Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
`PyPy <http://pypy.org/>`__ is also known to work.
The psutil documentation you're reading is distributed as a single HTML page.
@ -66,7 +68,7 @@ CPU
- **guest** *(Linux 2.6.24+)*
- **guest_nice** *(Linux 3.2.0+)*
When *percpu* is ``True`` return a list of nameduples for each logical CPU
When *percpu* is ``True`` return a list of namedtuples for each logical CPU
on the system.
First element of the list refers to first CPU, second element to second CPU
and so on.
@ -199,7 +201,7 @@ Memory
* **total**: total swap memory in bytes
* **used**: used swap memory in bytes
* **free**: free swap memory in bytes
* **percent**: the percentage usage
* **percent**: the percentage usage calculated as ``(total - available) / total * 100``
* **sin**: the number of bytes the system has swapped in from disk
(cumulative)
* **sout**: the number of bytes the system has swapped out from disk
@ -274,7 +276,7 @@ Disks
If *perdisk* is ``True`` return the same information for every physical disk
installed on the system as a dictionary with partition names as the keys and
the namedutuple described above as the values.
the namedtuple described above as the values.
See `examples/iotop.py <https://github.com/giampaolo/psutil/blob/master/examples/iotop.py>`__
for an example application.
@ -321,7 +323,7 @@ Network
.. function:: net_connections(kind='inet')
Return system-wide socket connections as a list of namedutples.
Return system-wide socket connections as a list of namedtuples.
Every namedtuple provides 7 attributes:
- **fd**: the socket file descriptor, if retrievable, else ``-1``.
@ -383,6 +385,7 @@ Network
| "all" | the sum of all the possible families and protocols |
+----------------+-----------------------------------------------------+
On OSX this function requires root privileges.
To get per-process connections use :meth:`Process.connections`.
Also, see
`netstat.py sample script <https://github.com/giampaolo/psutil/blob/master/examples/netstat.py>`__.
@ -390,17 +393,85 @@ Network
>>> import psutil
>>> psutil.net_connections()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None)
...]
.. note:: (OSX) :class:`psutil.AccessDenied` is always raised unless running
as root (lsof does the same).
.. note:: (Solaris) UNIX sockets are not supported.
*New in 2.1.0*
.. versionadded:: 2.1.0
.. function:: net_if_addrs()
Return the addresses associated to each NIC (network interface card)
installed on the system as a dictionary whose keys are the NIC names and
value is a list of namedtuples for each address assigned to the NIC.
Each namedtuple includes 4 fields:
- **family**
- **address**
- **netmask**
- **broadcast**
*family* can be either
`AF_INET <http://docs.python.org//library/socket.html#socket.AF_INET>`__,
`AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__
or :const:`psutil.AF_LINK`, which refers to a MAC address.
*address* is the primary address, *netmask* and *broadcast* may be ``None``.
Example::
>>> import psutil
>>> 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'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
>>>
See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__
for an example application.
.. note:: if you're interested in others families (e.g. AF_BLUETOOTH) you can
use the more powerful `netifaces <https://pypi.python.org/pypi/netifaces/>`__
extension.
.. note:: you can have more than one address of the same family associated
with each interface (that's why dict values are lists).
*New in 3.0.0*
.. function:: net_if_stats()
Return information about each NIC (network interface card) installed on the
system as a dictionary whose keys are the NIC names and value is a namedtuple
with the following fields:
- **isup**
- **duplex**
- **speed**
- **mtu**
*isup* is a boolean indicating whether the NIC is up and running, *duplex*
can be either :const:`NIC_DUPLEX_FULL`, :const:`NIC_DUPLEX_HALF` or
:const:`NIC_DUPLEX_UNKNOWN`, *speed* is the NIC speed expressed in mega bits
(MB), if it can't be determined (e.g. 'localhost') it will be set to ``0``,
*mtu* is the maximum transmission unit expressed in bytes.
See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__
for an example application.
Example:
>>> import psutil
>>> 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)}
*New in 3.0.0*
Other system info
@ -498,7 +569,7 @@ Functions
import psutil
def on_terminate(proc):
print("process {} terminated".format(proc))
print("process {} terminated with exit code {}".format(proc, proc.returncode))
procs = [...] # a list of Process instances
for p in procs:
@ -521,6 +592,18 @@ Exceptions
exists. "name" is the name the process had before disappearing
and gets set only if :meth:`Process.name()` was previosly called.
.. class:: ZombieProcess(pid, name=None, ppid=None, msg=None)
This may be raised by :class:`Process` class methods when querying a zombie
process on UNIX (Windows doesn't have zombie processes). Depending on the
method called the OS may be able to succeed in retrieving the process
information or not.
Note: this is a subclass of :class:`NoSuchProcess` so if you're not
interested in retrieving zombies (e.g. when using :func:`process_iter()`)
you can ignore this exception and just catch :class:`NoSuchProcess`.
*New in 3.0.0*
.. class:: AccessDenied(pid=None, name=None, msg=None)
Raised by :class:`Process` class methods when permission to perform an
@ -609,20 +692,24 @@ Process class
>>> datetime.datetime.fromtimestamp(p.create_time()).strftime("%Y-%m-%d %H:%M:%S")
'2011-03-05 18:03:52'
.. method:: as_dict(attrs=[], ad_value=None)
.. method:: as_dict(attrs=None, ad_value=None)
Utility method returning process information as a hashable dictionary.
If *attrs* is specified it must be a list of strings reflecting available
:class:`Process` class's attribute names (e.g. ``['cpu_times', 'name']``)
else all public (read only) attributes are assumed. *ad_value* is the
value which gets assigned to a dict key in case :class:`AccessDenied`
exception is raised when retrieving that particular process information.
or :class:`ZombieProcess` exception is raised when retrieving that
particular process information.
>>> import psutil
>>> p = psutil.Process()
>>> p.as_dict(attrs=['pid', 'name', 'username'])
{'username': 'giampaolo', 'pid': 12366, 'name': 'python'}
.. versionchanged:: 3.0.0 *ad_value* is used also when incurring into
:class:`ZombieProcess` exception, not only :class:`AccessDenied`
.. method:: parent()
Utility method which returns the parent process as a :class:`Process`
@ -646,7 +733,7 @@ Process class
.. method:: uids()
The **real**, **effective** and **saved** user ids of this process as a
nameduple. This is the same as
namedtuple. This is the same as
`os.getresuid() <http://docs.python.org//library/os.html#os.getresuid>`__
but can be used for every process PID.
@ -655,7 +742,7 @@ Process class
.. method:: gids()
The **real**, **effective** and **saved** group ids of this process as a
nameduple. This is the same as
namedtuple. This is the same as
`os.getresgid() <http://docs.python.org//library/os.html#os.getresgid>`__
but can be used for every process PID.
@ -682,6 +769,13 @@ Process class
10
>>>
Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this
functionality is also available as
`os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__
and
`os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__
(UNIX only).
On Windows this is available as well by using
`GetPriorityClass <http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx>`__
and `SetPriorityClass <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__
@ -692,12 +786,6 @@ Process class
>>> p.nice(psutil.HIGH_PRIORITY_CLASS)
Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this
same functionality is available as
`os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__
and
`os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__.
.. method:: ionice(ioclass=None, value=None)
Get or set
@ -714,7 +802,7 @@ Process class
>>> p = psutil.Process()
>>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # set
>>> p.ionice() # get
pionice(ioclass=3, value=0)
pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0)
>>>
On Windows only *ioclass* is used and it can be set to ``2`` (normal),
@ -722,6 +810,10 @@ Process class
Availability: Linux and Windows > Vista
.. versionchanged:: 3.0.0 on >= Python 3.4 the returned ``ioclass``
constant is an `enum <https://docs.python.org/3/library/enum.html#module-enum>`__
instead of a plain integer.
.. method:: rlimit(resource, limits=None)
Get or set process resource limits (see
@ -761,7 +853,7 @@ Process class
>>> p.io_counters()
pio(read_count=454556, write_count=3456, read_bytes=110592, write_bytes=0)
Availability: all platforms except OSX
Availability: all platforms except OSX and Solaris
.. method:: num_ctx_switches()
@ -836,7 +928,8 @@ Process class
`CPU affinity <http://www.linuxjournal.com/article/6799?page=0,0>`__.
CPU affinity consists in telling the OS to run a certain process on a
limited set of CPUs only. The number of eligible CPUs can be obtained with
``list(range(psutil.cpu_count()))``.
``list(range(psutil.cpu_count()))``. On set raises ``ValueError`` in case
an invalid CPU number is specified.
>>> import psutil
>>> psutil.cpu_count()
@ -845,9 +938,17 @@ Process class
>>> p.cpu_affinity() # get
[0, 1, 2, 3]
>>> p.cpu_affinity([0]) # set; from now on, process will run on CPU #0 only
>>> p.cpu_affinity()
[0]
>>>
>>> # reset affinity against all CPUs
>>> all_cpus = list(range(psutil.cpu_count()))
>>> p.cpu_affinity(all_cpus)
>>>
Availability: Linux, Windows
Availability: Linux, Windows, BSD
.. versionchanged:: 2.2.0 added support for FreeBSD
.. method:: memory_info()
@ -903,7 +1004,7 @@ Process class
.. method:: memory_maps(grouped=True)
Return process's mapped memory regions as a list of nameduples whose
Return process's mapped memory regions as a list of namedtuples whose
fields are variable depending on the platform. As such, portable
applications should rely on namedtuple's `path` and `rss` fields only.
This method is useful to obtain a detailed representation of process
@ -958,15 +1059,31 @@ Process class
the absolute file name and the file descriptor number (on Windows this is
always ``-1``). Example:
>>> import psutil
>>> f = open('file.ext', 'w')
>>> p = psutil.Process()
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)]
>>> import psutil
>>> f = open('file.ext', 'w')
>>> p = psutil.Process()
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)]
.. warning::
on Windows this is not fully reliable as due to some limitations of the
Windows API the underlying implementation may hang when retrieving
certain file handles.
In order to work around that psutil on Windows Vista (and higher) spawns
a thread and kills it if it's not responding after 100ms.
That implies that on Windows this method is not guaranteed to enumerate
all regular file handles (see full discusion
`here <https://github.com/giampaolo/psutil/pull/597>`_).
.. warning::
on FreeBSD this method can return files with a 'null' path (see
`issue 595 <https://github.com/giampaolo/psutil/pull/595>`_).
.. versionchanged:: 3.1.0 no longer hangs on Windows.
.. method:: connections(kind="inet")
Return socket connections opened by process as a list of namedutples.
Return socket connections opened by process as a list of namedtuples.
To get system-wide connections use :func:`psutil.net_connections()`.
Every namedtuple provides 6 attributes:
@ -1032,10 +1149,10 @@ Process class
>>> p.name()
'firefox'
>>> p.connections()
[pconn(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')]
.. method:: is_running()
@ -1125,7 +1242,7 @@ Popen class
:meth:`send_signal() <psutil.Process.send_signal()>`,
:meth:`terminate() <psutil.Process.terminate()>` and
:meth:`kill() <psutil.Process.kill()>`
so that you don't accidentally terminate another process, fixing
so that you can't accidentally terminate another process, fixing
http://bugs.python.org/issue6973.
>>> import psutil
@ -1197,6 +1314,10 @@ Constants
Availability: Windows
.. versionchanged:: 3.0.0 on Python >= 3.4 these constants are
`enums <https://docs.python.org/3/library/enum.html#module-enum>`__
instead of a plain integer.
.. _const-ioprio:
.. data:: IOPRIO_CLASS_NONE
IOPRIO_CLASS_RT
@ -1220,6 +1341,10 @@ Constants
Availability: Linux
.. versionchanged:: 3.0.0 on Python >= 3.4 thse constants are
`enums <https://docs.python.org/3/library/enum.html#module-enum>`__
instead of a plain integer.
.. _const-rlimit:
.. data:: RLIMIT_INFINITY
RLIMIT_AS
@ -1245,3 +1370,31 @@ Constants
`man prlimit <http://linux.die.net/man/2/prlimit>`__ for futher information.
Availability: Linux
.. _const-aflink:
.. data:: AF_LINK
Constant which identifies a MAC address associated with a network interface.
To be used in conjunction with :func:`psutil.net_if_addrs()`.
*New in 3.0.0*
.. _const-duplex:
.. data:: NIC_DUPLEX_FULL
NIC_DUPLEX_HALF
NIC_DUPLEX_UNKNOWN
Constants which identifies whether a NIC (network interface card) has full or
half mode speed. NIC_DUPLEX_FULL means the NIC is able to send and receive
data (files) simultaneously, NIC_DUPLEX_FULL means the NIC can either send or
receive data at a time.
To be used in conjunction with :func:`psutil.net_if_stats()`.
*New in 3.0.0*
Development guide
=================
If you plan on hacking on psutil (e.g. want to add a new feature or fix a bug)
take a look at the
`development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_.

11
python/psutil/docs/xxx Normal file
View File

@ -0,0 +1,11 @@
cpu 1974613 1749 485728 6305758 80280 15 5924 0 0 0
cpu0 519156 374 132999 5977865 72925 10 1458 0 0 0
cpu1 524667 401 125931 108960 2110 4 2214 0 0 0
cpu2 462286 520 117046 109514 2666 0 828 0 0 0
cpu3 468502 453 109750 109418 2578 0 1424 0 0 0

View File

@ -18,7 +18,6 @@ Device Total Used Free Use % Type Mount
import sys
import os
import psutil
from psutil._compat import print_
def bytes2human(n):
@ -40,8 +39,8 @@ def bytes2human(n):
def main():
templ = "%-17s %8s %8s %8s %5s%% %9s %s"
print_(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
"Mount"))
print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type",
"Mount"))
for part in psutil.disk_partitions(all=False):
if os.name == 'nt':
if 'cdrom' in part.opts or part.fstype == '':
@ -50,7 +49,7 @@ def main():
# partition or just hang.
continue
usage = psutil.disk_usage(part.mountpoint)
print_(templ % (
print(templ % (
part.device,
bytes2human(usage.total),
bytes2human(usage.used),

View File

@ -14,15 +14,14 @@ Swap: 0 0 0
"""
import psutil
from psutil._compat import print_
def main():
virt = psutil.virtual_memory()
swap = psutil.swap_memory()
templ = "%-7s %10s %10s %10s %10s %10s %10s"
print_(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
print_(templ % (
print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache'))
print(templ % (
'Mem:',
int(virt.total / 1024),
int(virt.used / 1024),
@ -30,7 +29,7 @@ def main():
int(getattr(virt, 'shared', 0) / 1024),
int(getattr(virt, 'buffers', 0) / 1024),
int(getattr(virt, 'cached', 0) / 1024)))
print_(templ % (
print(templ % (
'Swap:', int(swap.total / 1024),
int(swap.used / 1024),
int(swap.free / 1024),

View File

@ -0,0 +1,78 @@
#!/usr/bin/env python
# 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.
"""
A clone of 'ifconfig' on UNIX.
$ python examples/ifconfig.py
lo (speed=0MB, duplex=?, mtu=65536, up=yes):
IPv4 address : 127.0.0.1
broadcast : 127.0.0.1
netmask : 255.0.0.0
IPv6 address : ::1
netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
MAC address : 00:00:00:00:00:00
broadcast : 00:00:00:00:00:00
wlan0 (speed=0MB, duplex=?, mtu=1500, up=yes):
IPv4 address : 10.0.3.1
broadcast : 10.0.3.255
netmask : 255.255.255.0
IPv6 address : fe80::3005:adff:fe31:8698
netmask : ffff:ffff:ffff:ffff::
MAC address : 32:05:ad:31:86:98
broadcast : ff:ff:ff:ff:ff:ff
eth0 (speed=100MB, duplex=full, mtu=1500, up=yes):
IPv4 address : 192.168.1.2
broadcast : 192.168.1.255
netmask : 255.255.255.0
IPv6 address : fe80::c685:8ff:fe45:641
netmask : ffff:ffff:ffff:ffff::
MAC address : c4:85:08:45:06:41
broadcast : ff:ff:ff:ff:ff:ff
"""
from __future__ import print_function
import socket
import psutil
af_map = {
socket.AF_INET: 'IPv4',
socket.AF_INET6: 'IPv6',
psutil.AF_LINK: 'MAC',
}
duplex_map = {
psutil.NIC_DUPLEX_FULL: "full",
psutil.NIC_DUPLEX_HALF: "half",
psutil.NIC_DUPLEX_UNKNOWN: "?",
}
def main():
stats = psutil.net_if_stats()
for nic, addrs in psutil.net_if_addrs().items():
if nic in stats:
print("%s (speed=%sMB, duplex=%s, mtu=%s, up=%s):" % (
nic, stats[nic].speed, duplex_map[stats[nic].duplex],
stats[nic].mtu, "yes" if stats[nic].isup else "no"))
else:
print("%s:" % (nic))
for addr in addrs:
print(" %-8s" % af_map.get(addr.family, addr.family), end="")
print(" address : %s" % addr.address)
if addr.broadcast:
print(" broadcast : %s" % addr.broadcast)
if addr.netmask:
print(" netmask : %s" % addr.netmask)
print("")
if __name__ == '__main__':
main()

View File

@ -30,14 +30,15 @@ PID USER DISK READ DISK WRITE COMMAND
Author: Giampaolo Rodola' <g.rodola@gmail.com>
"""
import os
import sys
import psutil
if not hasattr(psutil.Process, 'io_counters') or os.name != 'posix':
sys.exit('platform not supported')
import time
import curses
import atexit
import time
import sys
try:
import curses
except ImportError:
sys.exit('platform not supported')
import psutil
# --- curses stuff
@ -116,7 +117,7 @@ def poll(interval):
if not p._cmdline:
p._cmdline = p.name()
p._username = p.username()
except psutil.NoSuchProcess:
except (psutil.NoSuchProcess, psutil.ZombieProcess):
procs.remove(p)
disks_after = psutil.disk_io_counters()
@ -167,7 +168,7 @@ def refresh_window(procs, disks_read, disks_write):
def main():
try:
interval = 0
while 1:
while True:
args = poll(interval)
refresh_window(*args)
interval = 1

View File

@ -31,7 +31,6 @@ Sout : 0B
"""
import psutil
from psutil._compat import print_
def bytes2human(n):
@ -56,13 +55,13 @@ def pprint_ntuple(nt):
value = getattr(nt, name)
if name != 'percent':
value = bytes2human(value)
print_('%-10s : %7s' % (name.capitalize(), value))
print('%-10s : %7s' % (name.capitalize(), value))
def main():
print_('MEMORY\n------')
print('MEMORY\n------')
pprint_ntuple(psutil.virtual_memory())
print_('\nSWAP\n----')
print('\nSWAP\n----')
pprint_ntuple(psutil.swap_memory())
if __name__ == '__main__':

View File

@ -23,7 +23,6 @@ import socket
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
import psutil
from psutil._compat import print_
AD = "-"
@ -38,7 +37,7 @@ proto_map = {
def main():
templ = "%-5s %-30s %-30s %-13s %-6s %s"
print_(templ % (
print(templ % (
"Proto", "Local address", "Remote address", "Status", "PID",
"Program name"))
proc_names = {}
@ -52,7 +51,7 @@ def main():
raddr = ""
if c.raddr:
raddr = "%s:%s" % (c.raddr)
print_(templ % (
print(templ % (
proto_map[(c.family, c.type)],
laddr,
raddr or AD,

View File

@ -31,13 +31,13 @@ pkts-sent 0 0
pkts-recv 1214470 0
"""
import sys
import os
if os.name != 'posix':
sys.exit('platform not supported')
import atexit
import curses
import time
import sys
try:
import curses
except ImportError:
sys.exit('platform not supported')
import psutil

53
python/psutil/examples/pidof.py Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
# Copyright (c) 2009, Giampaolo Rodola', karthikrev. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
A clone of 'pidof' cmdline utility.
$ pidof python
1140 1138 1136 1134 1133 1129 1127 1125 1121 1120 1119
"""
from __future__ import print_function
import psutil
import sys
def pidof(pgname):
pids = []
for proc in psutil.process_iter():
# search for matches in the process name and cmdline
try:
name = proc.name()
except psutil.Error:
pass
else:
if name == pgname:
pids.append(str(proc.pid))
continue
try:
cmdline = proc.cmdline()
except psutil.Error:
pass
else:
if cmdline and cmdline[0] == pgname:
pids.append(str(proc.pid))
return pids
def main():
if len(sys.argv) != 2:
sys.exit('usage: %s pgname' % __file__)
else:
pgname = sys.argv[1]
pids = pidof(pgname)
if pids:
print(" ".join(pids))
if __name__ == '__main__':
main()

View File

@ -33,26 +33,25 @@ ffffffffff600000 0K r-xp [vsyscall]
import sys
import psutil
from psutil._compat import print_
def main():
if len(sys.argv) != 2:
sys.exit('usage: pmap <pid>')
p = psutil.Process(int(sys.argv[1]))
print_("pid=%s, name=%s" % (p.pid, p.name()))
print("pid=%s, name=%s" % (p.pid, p.name()))
templ = "%-16s %10s %-7s %s"
print_(templ % ("Address", "RSS", "Mode", "Mapping"))
print(templ % ("Address", "RSS", "Mode", "Mapping"))
total_rss = 0
for m in p.memory_maps(grouped=False):
total_rss += m.rss
print_(templ % (
print(templ % (
m.addr.split('-')[0].zfill(16),
str(m.rss / 1024) + 'K',
m.perms,
m.path))
print_("-" * 33)
print_(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
print("-" * 33)
print(templ % ("Total", str(total_rss / 1024) + 'K', '', ''))
if __name__ == '__main__':
main()

View File

@ -68,8 +68,8 @@ def run(pid):
try:
p = psutil.Process(pid)
pinfo = p.as_dict(ad_value=ACCESS_DENIED)
except psutil.NoSuchProcess:
sys.exit(str(sys.exc_info()[1]))
except psutil.NoSuchProcess as err:
sys.exit(str(err))
try:
parent = p.parent()
@ -79,13 +79,19 @@ def run(pid):
parent = ''
except psutil.Error:
parent = ''
started = datetime.datetime.fromtimestamp(
pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
if pinfo['create_time'] != ACCESS_DENIED:
started = datetime.datetime.fromtimestamp(
pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
else:
started = ACCESS_DENIED
io = pinfo.get('io_counters', ACCESS_DENIED)
mem = '%s%% (resident=%s, virtual=%s) ' % (
round(pinfo['memory_percent'], 1),
convert_bytes(pinfo['memory_info'].rss),
convert_bytes(pinfo['memory_info'].vms))
if pinfo['memory_info'] != ACCESS_DENIED:
mem = '%s%% (resident=%s, virtual=%s) ' % (
round(pinfo['memory_percent'], 1),
convert_bytes(pinfo['memory_info'].rss),
convert_bytes(pinfo['memory_info'].vms))
else:
mem = ACCESS_DENIED
children = p.children()
print_('pid', pinfo['pid'])
@ -101,8 +107,7 @@ def run(pid):
print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
if POSIX:
print_('terminal', pinfo['terminal'] or '')
if hasattr(p, 'getcwd'):
print_('cwd', pinfo['cwd'])
print_('cwd', pinfo['cwd'])
print_('memory', mem)
print_('cpu', '%s%% (user=%s, system=%s)' % (
pinfo['cpu_percent'],

View File

@ -16,7 +16,6 @@ import os
import time
import psutil
from psutil._compat import print_
def main():
@ -27,8 +26,8 @@ def main():
if os.name == 'posix':
attrs.append('uids')
attrs.append('terminal')
print_(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
"START", "TIME", "COMMAND"))
print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY",
"START", "TIME", "COMMAND"))
for p in psutil.process_iter():
try:
pinfo = p.as_dict(attrs, ad_value='')
@ -65,16 +64,17 @@ def main():
int(pinfo['memory_info'].rss / 1024) or '?'
memp = pinfo['memory_percent'] and \
round(pinfo['memory_percent'], 1) or '?'
print_(templ % (user[:10],
pinfo['pid'],
pinfo['cpu_percent'],
memp,
vms,
rss,
pinfo.get('terminal', '') or '?',
ctime,
cputime,
pinfo['name'].strip() or '?'))
print(templ % (
user[:10],
pinfo['pid'],
pinfo['cpu_percent'],
memp,
vms,
rss,
pinfo.get('terminal', '') or '?',
ctime,
cputime,
pinfo['name'].strip() or '?'))
if __name__ == '__main__':

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
# 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.
"""
Similar to 'ps aux --forest' on Linux, prints the process list
as a tree structure.
$ python examples/pstree.py
0 ?
|- 1 init
| |- 289 cgmanager
| |- 616 upstart-socket-bridge
| |- 628 rpcbind
| |- 892 upstart-file-bridge
| |- 907 dbus-daemon
| |- 978 avahi-daemon
| | `_ 979 avahi-daemon
| |- 987 NetworkManager
| | |- 2242 dnsmasq
| | `_ 10699 dhclient
| |- 993 polkitd
| |- 1061 getty
| |- 1066 su
| | `_ 1190 salt-minion...
...
"""
from __future__ import print_function
import collections
import sys
import psutil
def print_tree(parent, tree, indent=''):
try:
name = psutil.Process(parent).name()
except psutil.Error:
name = "?"
print(parent, name)
if parent not in tree:
return
children = tree[parent][:-1]
for child in children:
sys.stdout.write(indent + "|- ")
print_tree(child, tree, indent + "| ")
child = tree[parent][-1]
sys.stdout.write(indent + "`_ ")
print_tree(child, tree, indent + " ")
def main():
# construct a dict where 'values' are all the processes
# having 'key' as their parent
tree = collections.defaultdict(list)
for p in psutil.process_iter():
try:
tree[p.ppid()].append(p.pid)
except (psutil.NoSuchProcess, psutil.ZombieProcess):
pass
# on systems supporting PID 0, PID 0's parent is usually 0
if 0 in tree and 0 in tree[0]:
tree[0].remove(0)
print_tree(min(tree), tree)
if __name__ == '__main__':
main()

View File

@ -34,14 +34,15 @@ PID USER NI VIRT RES CPU% MEM% TIME+ NAME
...
"""
import os
import sys
if os.name != 'posix':
sys.exit('platform not supported')
import atexit
import curses
import time
from datetime import datetime, timedelta
import atexit
import os
import time
import sys
try:
import curses
except ImportError:
sys.exit('platform not supported')
import psutil
@ -221,7 +222,7 @@ def refresh_window(procs, procs_status):
def main():
try:
interval = 0
while 1:
while True:
args = poll(interval)
refresh_window(*args)
interval = 1

View File

@ -18,13 +18,12 @@ giampaolo pts/9 2014-02-27 01:32 (:0)
from datetime import datetime
import psutil
from psutil._compat import print_
def main():
users = psutil.users()
for user in users:
print_("%-15s %-15s %s (%s)" % (
print("%-15s %-15s %s (%s)" % (
user.name,
user.terminal or '-',
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),

View File

@ -7,18 +7,16 @@ rem psutil ("make.bat build", "make.bat install") and running tests
rem ("make.bat test").
rem
rem This script is modeled after my Windows installation which uses:
rem - mingw32 for Python 2.4 and 2.5
rem - Visual studio 2008 for Python 2.6, 2.7, 3.2
rem - Visual studio 2010 for Python 3.3+
rem ...therefore it might not work on your Windows installation.
rem
rem By default C:\Python27\python.exe is used.
rem To compile for a specific Python version run:
rem set PYTHON=C:\Python34\python.exe & make.bat build
rem
rem set PYTHON=C:\Python24\python.exe & make.bat build
rem
rem If you compile by using mingw on Python 2.4 and 2.5 you need to patch
rem distutils first: http://stackoverflow.com/questions/13592192
rem To use a different test script:
rem set PYTHON=C:\Python34\python.exe & set TSCRIPT=foo.py & make.bat test
rem ==========================================================================
if "%PYTHON%" == "" (
@ -28,8 +26,16 @@ if "%TSCRIPT%" == "" (
set TSCRIPT=test\test_psutil.py
)
rem Needed to compile using Mingw.
set PATH=C:\MinGW\bin;%PATH%
set PYTHON26=C:\Python26\python.exe
set PYTHON27=C:\Python27\python.exe
set PYTHON33=C:\Python33\python.exe
set PYTHON34=C:\Python34\python.exe
set PYTHON26-64=C:\Python26-64\python.exe
set PYTHON27-64=C:\Python27-64\python.exe
set PYTHON33-64=C:\Python33-64\python.exe
set PYTHON34-64=C:\Python34-64\python.exe
set ALL_PYTHONS=%PYTHON26% %PYTHON27% %PYTHON33% %PYTHON34% %PYTHON26-64% %PYTHON27-64% %PYTHON33-64% %PYTHON34-64%
rem Needed to locate the .pypirc file and upload exes on PYPI.
set HOME=%USERPROFILE%
@ -40,23 +46,21 @@ if "%1" == "help" (
:help
echo Run `make ^<target^>` where ^<target^> is one of:
echo build compile without installing
echo build-exes create exe installers in dist directory
echo build-wheels create wheel installers in dist directory
echo build-all build exes + wheels
echo clean clean build files
echo flake8 run flake8
echo install compile and install
echo memtest run memory leak tests
echo setup-env install pip, unittest2, wheels for all python versions
echo setup-dev-env install pip, pywin32, wheels, etc. for all python versions
echo test run tests
echo test-memleaks run memory leak tests
echo test-process run process related tests
echo test-system run system APIs related tests
echo uninstall uninstall
echo upload-exes upload exe installers on pypi
echo upload-wheels upload wheel installers on pypi
echo upload-all upload exes + wheels
goto :eof
)
if "%1" == "clean" (
:clean
for /r %%R in (__pycache__) do if exist %%R (rmdir /S /Q %%R)
for /r %%R in (*.pyc) do if exist %%R (del /s %%R)
for /r %%R in (*.pyd) do if exist %%R (del /s %%R)
@ -71,31 +75,25 @@ if "%1" == "clean" (
if "%1" == "build" (
:build
if %PYTHON%==C:\Python24\python.exe (
%PYTHON% setup.py build -c mingw32
) else if %PYTHON%==C:\Python25\python.exe (
%PYTHON% setup.py build -c mingw32
) else (
%PYTHON% setup.py build
)
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
%PYTHON% setup.py build
if %errorlevel% neq 0 goto :error
rem copies *.pyd files in ./psutil directory in order to allow
rem "import psutil" when using the interactive interpreter from
rem within this directory.
%PYTHON% setup.py build_ext -i
if %errorlevel% neq 0 goto :error
goto :eof
)
if "%1" == "install" (
:install
if %PYTHON%==C:\Python24\python.exe (
%PYTHON% setup.py build -c mingw32 install
) else if %PYTHON%==C:\Python25\python.exe (
%PYTHON% setup.py build -c mingw32 install
) else (
%PYTHON% setup.py build install
)
call :build
%PYTHON% setup.py install
goto :eof
)
if "%1" == "uninstall" (
:uninstall
for %%A in ("%PYTHON%") do (
set folder=%%~dpA
)
@ -106,125 +104,98 @@ if "%1" == "uninstall" (
)
if "%1" == "test" (
:test
call :install
%PYTHON% %TSCRIPT%
goto :eof
)
if "%1" == "test-process" (
:test
call :install
%PYTHON% -m unittest -v test.test_psutil.TestProcess
goto :eof
)
if "%1" == "test-system" (
:test
call :install
%PYTHON% -m unittest -v test.test_psutil.TestSystem
goto :eof
)
if "%1" == "test-memleaks" (
:memtest
call :install
%PYTHON% test\test_memory_leaks.py
goto :eof
)
if "%1" == "build-exes" (
:build-exes
rem mingw 32 versions
C:\Python24\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst || goto :error
rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
C:\Python26\python.exe setup.py build bdist_wininst || goto :error
C:\Python27\python.exe setup.py build bdist_wininst || goto :error
C:\Python33\python.exe setup.py build bdist_wininst || goto :error
C:\Python34\python.exe setup.py build bdist_wininst || goto :error
rem 64 bit versions
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
rem http://stackoverflow.com/questions/11072521/
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
if "%1" == "build-all" (
:build-all
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
C:\Python27-64\python.exe setup.py build bdist_wininst || goto :error
C:\Python33-64\python.exe setup.py build bdist_wininst || goto :error
C:\Python34-64\python.exe setup.py build bdist_wininst || goto :error
for %%P in (%ALL_PYTHONS%) do (
@echo ------------------------------------------------
@echo building exe for %%P
@echo ------------------------------------------------
%%P setup.py build bdist_wininst || goto :error
@echo ------------------------------------------------
@echo building wheel for %%P
@echo ------------------------------------------------
%%P setup.py build bdist_wheel || goto :error
)
echo OK
goto :eof
)
if "%1" == "upload-exes" (
if "%1" == "upload-all" (
:upload-exes
rem mingw 32 versions
C:\Python25\python.exe setup.py build -c mingw32 bdist_wininst upload || goto :error
rem "standard" 32 bit versions, using VS 2008 (2.6, 2.7) or VS 2010 (3.3+)
C:\Python26\python.exe setup.py bdist_wininst upload || goto :error
C:\Python27\python.exe setup.py bdist_wininst upload || goto :error
C:\Python33\python.exe setup.py bdist_wininst upload || goto :error
C:\Python34\python.exe setup.py bdist_wininst upload || goto :error
rem 64 bit versions
C:\Python27-64\python.exe setup.py build bdist_wininst upload || goto :error
C:\Python33-64\python.exe setup.py build bdist_wininst upload || goto :error
C:\Python34-64\python.exe setup.py build bdist_wininst upload || goto :error
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
for %%P in (%ALL_PYTHONS%) do (
@echo ------------------------------------------------
@echo uploading exe for %%P
@echo ------------------------------------------------
%%P setup.py build bdist_wininst upload || goto :error
@echo ------------------------------------------------
@echo uploading wheel for %%P
@echo ------------------------------------------------
%%P setup.py build bdist_wheel upload || goto :error
)
echo OK
goto :eof
)
if "%1" == "setup-env" (
if "%1" == "setup-dev-env" (
:setup-env
C:\python27\python.exe -c "import urllib2; url = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); data = url.read(); f = open('get-pip.py', 'w'); f.write(data)"
C:\python26\python.exe get-pip.py & C:\python26\scripts\pip install unittest2 wheel --upgrade
C:\python27\python.exe get-pip.py & C:\python27\scripts\pip install wheel --upgrade
C:\python33\python.exe get-pip.py & C:\python33\scripts\pip install wheel --upgrade
C:\python34\scripts\easy_install.exe wheel
rem 64-bit versions
C:\python27-64\python.exe get-pip.py & C:\python27-64\scripts\pip install wheel --upgrade
C:\python33-64\python.exe get-pip.py & C:\python33-64\scripts\pip install wheel --upgrade
C:\python34-64\scripts\easy_install.exe wheel
@echo ------------------------------------------------
@echo downloading pip installer
@echo ------------------------------------------------
C:\python27\python.exe -c "import urllib2; r = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); open('get-pip.py', 'wb').write(r.read())"
for %%P in (%ALL_PYTHONS%) do (
@echo ------------------------------------------------
@echo installing pip for %%P
@echo ------------------------------------------------
%%P get-pip.py
)
for %%P in (%ALL_PYTHONS%) do (
@echo ------------------------------------------------
@echo installing deps for %%P
@echo ------------------------------------------------
rem mandatory / for unittests
%%P -m pip install unittest2 ipaddress mock wmi wheel pypiwin32 --upgrade
rem nice to have
%%P -m pip install ipdb pep8 pyflakes flake8 --upgrade
)
goto :eof
)
if "%1" == "build-wheels" (
:build-wheels
C:\Python26\python.exe setup.py build bdist_wheel || goto :error
C:\Python27\python.exe setup.py build bdist_wheel || goto :error
C:\Python33\python.exe setup.py build bdist_wheel || goto :error
C:\Python34\python.exe setup.py build bdist_wheel || goto :error
rem 64 bit versions
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
rem http://stackoverflow.com/questions/11072521/
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
C:\Python27-64\python.exe setup.py build bdist_wheel || goto :error
C:\Python33-64\python.exe setup.py build bdist_wheel || goto :error
C:\Python34-64\python.exe setup.py build bdist_wheel || goto :error
echo OK
goto :eof
)
if "%1" == "upload-wheels" (
:build-wheels
C:\Python26\python.exe setup.py build bdist_wheel upload || goto :error
C:\Python27\python.exe setup.py build bdist_wheel upload || goto :error
C:\Python33\python.exe setup.py build bdist_wheel upload || goto :error
C:\Python34\python.exe setup.py build bdist_wheel upload || goto :error
rem 64 bit versions
rem Python 2.7 + VS 2008 requires vcvars64.bat to be run first:
rem http://stackoverflow.com/questions/11072521/
rem Windows SDK and .NET Framework 3.5 SP1 also need to be installed (sigh)
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
C:\Python27-64\python.exe setup.py build bdist_wheel upload || goto :error
C:\Python33-64\python.exe setup.py build bdist_wheel upload || goto :error
C:\Python34-64\python.exe setup.py build bdist_wheel upload || goto :error
echo OK
if "%1" == "flake8" (
:flake8
%PYTHON% -c "from flake8.main import main; main()"
goto :eof
)
goto :help
:error
echo last command exited with error code %errorlevel%
exit /b %errorlevel%
@echo ------------------------------------------------
@echo last command exited with error code %errorlevel%
@echo ------------------------------------------------
@exit /b %errorlevel%
goto :eof

View File

@ -0,0 +1,434 @@
Metadata-Version: 1.1
Name: psutil
Version: 3.1.1
Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python.
Home-page: https://github.com/giampaolo/psutil
Author: Giampaolo Rodola
Author-email: g.rodola <at> gmail <dot> com
License: BSD
Description: .. image:: https://img.shields.io/pypi/dm/psutil.svg
:target: https://pypi.python.org/pypi/psutil#downloads
:alt: Downloads this month
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
:target: https://travis-ci.org/giampaolo/psutil
:alt: Linux tests (Travis)
.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true
:target: https://ci.appveyor.com/project/giampaolo/psutil
:alt: Windows tests (Appveyor)
.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github
:target: https://coveralls.io/github/giampaolo/psutil?branch=master
:alt: Test coverage (coverall.io)
.. image:: https://img.shields.io/pypi/v/psutil.svg
: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/scrutinizer/g/giampaolo/psutil.svg
:target: https://scrutinizer-ci.com/g/giampaolo/psutil/
:alt: Code quality (scrutinizer-ci.com)
.. 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>`_
- `Documentation <http://pythonhosted.org/psutil/>`_
- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_
- `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 (python system and process utilities) is a cross-platform library for
retrieving information on **running processes** and **system utilization**
(CPU, memory, disks, network) 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 command line
tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice,
ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports
**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and
**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of
Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version).
`PyPy <http://pypy.org/>`__ is also known to work.
====================
Example applications
====================
.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/top.png
:alt: top
.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/nettop.png
:alt: nettop
.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png
:target: http://psutil.googlecode.com/svn/wiki/images/iotop.png
:alt: iotop
See also:
* https://github.com/nicolargo/glances
* https://github.com/google/grr
* https://github.com/Jahaja/psdash
==============
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
>>>
Memory
======
.. code-block:: python
>>> psutil.virtual_memory()
svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336)
>>> psutil.swap_memory()
sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944)
>>>
Disks
=====
.. code-block:: python
>>> 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)
>>>
Network
=======
.. code-block:: python
>>> 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()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None),
pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 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'),
snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')],
'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'),
snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None),
snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]}
>>>
>>> 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)}
Other system info
=================
.. code-block:: python
>>> psutil.users()
[user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
>>>
>>> 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.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)
>>> p.cpu_percent(interval=1.0)
12.1
>>> p.cpu_affinity()
[0, 1, 2, 3]
>>> p.cpu_affinity([0]) # set
>>>
>>> p.memory_percent()
0.63423
>>>
>>> p.memory_info()
pmem(rss=7471104, vms=68513792)
>>> p.memory_info_ex()
extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
>>> p.memory_maps()
[pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0),
pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0),
...]
>>>
>>> p.io_counters()
pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
>>>
>>> p.open_files()
[popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
>>>
>>> p.connections()
[pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'),
pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'),
pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'),
pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 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.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
>>> for p in psutil.process_iter():
... print(p)
...
psutil.Process(pid=1, name='init')
psutil.Process(pid=2, name='kthreadd')
psutil.Process(pid=3, name='ksoftirqd/0')
...
>>>
>>> def on_terminate(proc):
... print("process {} terminated".format(proc))
...
>>> # waits for multiple processes to terminate
>>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate)
>>>
======
Donate
======
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 Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money.
I only ask for a small donation, but of course I appreciate any amount.
.. 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 <http://www.linkedin.com/in/grodola>`_.
============
Mailing list
============
http://groups.google.com/group/psutil/
========
Timeline
========
- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_
- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_
- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_
- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_
- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_
- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_
- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_
- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_
- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_
- 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_
- 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_
- 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_
- 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_
- 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_
- 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_
- 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_
- 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_
- 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_
- 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_
- 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_
- 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_
- 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_
- 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_
- 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_
- 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_
- 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_
- 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_
- 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_
- 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_
- 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_
- 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_
- 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_
- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_
- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_
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
Platform: Platform Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Environment :: Win32 (MS Windows)
Classifier: Intended Audience :: Developers
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
Classifier: Operating System :: OS Independent
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: SunOS/Solaris
Classifier: Operating System :: POSIX
Classifier: Programming Language :: C
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.0
Classifier: Programming Language :: Python :: 3.1
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
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
Classifier: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities

View File

@ -0,0 +1,96 @@
.coveragerc
.git-pre-commit
.gitignore
.travis.yml
CREDITS
HISTORY.rst
INSTALL.rst
LICENSE
MANIFEST.in
Makefile
README.rst
TODO
make.bat
setup.py
tox.ini
docs/Makefile
docs/README
docs/conf.py
docs/index.rst
docs/make.bat
docs/xxx
docs/_static/copybutton.js
docs/_static/favicon.ico
docs/_static/logo.png
docs/_static/sidebar.js
docs/_template/globaltoc.html
docs/_template/indexcontent.html
docs/_template/indexsidebar.html
docs/_template/page.html
docs/_themes/pydoctheme/theme.conf
docs/_themes/pydoctheme/static/pydoctheme.css
examples/disk_usage.py
examples/free.py
examples/ifconfig.py
examples/iotop.py
examples/killall.py
examples/meminfo.py
examples/netstat.py
examples/nettop.py
examples/pidof.py
examples/pmap.py
examples/process_detail.py
examples/ps.py
examples/pstree.py
examples/top.py
examples/who.py
psutil/__init__.py
psutil/_common.py
psutil/_compat.py
psutil/_psbsd.py
psutil/_pslinux.py
psutil/_psosx.py
psutil/_psposix.py
psutil/_pssunos.py
psutil/_psutil_bsd.c
psutil/_psutil_bsd.h
psutil/_psutil_common.c
psutil/_psutil_common.h
psutil/_psutil_linux.c
psutil/_psutil_linux.h
psutil/_psutil_osx.c
psutil/_psutil_osx.h
psutil/_psutil_posix.c
psutil/_psutil_posix.h
psutil/_psutil_sunos.c
psutil/_psutil_sunos.h
psutil/_psutil_windows.c
psutil/_psutil_windows.h
psutil/_pswindows.py
psutil.egg-info/PKG-INFO
psutil.egg-info/SOURCES.txt
psutil.egg-info/dependency_links.txt
psutil.egg-info/top_level.txt
psutil/arch/bsd/process_info.c
psutil/arch/bsd/process_info.h
psutil/arch/osx/process_info.c
psutil/arch/osx/process_info.h
psutil/arch/windows/glpi.h
psutil/arch/windows/inet_ntop.c
psutil/arch/windows/inet_ntop.h
psutil/arch/windows/ntextapi.h
psutil/arch/windows/process_handles.c
psutil/arch/windows/process_handles.h
psutil/arch/windows/process_info.c
psutil/arch/windows/process_info.h
psutil/arch/windows/security.c
psutil/arch/windows/security.h
test/README.rst
test/_bsd.py
test/_linux.py
test/_osx.py
test/_posix.py
test/_sunos.py
test/_windows.py
test/test_memory_leaks.py
test/test_psutil.py

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
psutil

File diff suppressed because it is too large Load Diff

View File

@ -8,19 +8,23 @@
from __future__ import division
import errno
import functools
import os
import socket
import stat
import sys
import warnings
from collections import namedtuple
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
try:
import threading
except ImportError:
import dummy_threading as threading
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
if sys.version_info >= (3, 4):
import enum
else:
enum = None
from psutil._compat import namedtuple, wraps
# --- constants
@ -53,6 +57,18 @@ CONN_LISTEN = "LISTEN"
CONN_CLOSING = "CLOSING"
CONN_NONE = "NONE"
if enum is None:
NIC_DUPLEX_FULL = 2
NIC_DUPLEX_HALF = 1
NIC_DUPLEX_UNKNOWN = 0
else:
class NicDuplex(enum.IntEnum):
NIC_DUPLEX_FULL = 2
NIC_DUPLEX_HALF = 1
NIC_DUPLEX_UNKNOWN = 0
globals().update(NicDuplex.__members__)
# --- functions
@ -82,7 +98,7 @@ def memoize(fun):
>>> foo.cache_clear()
>>>
"""
@wraps(fun)
@functools.wraps(fun)
def wrapper(*args, **kwargs):
key = (args, frozenset(sorted(kwargs.items())))
lock.acquire()
@ -109,43 +125,6 @@ def memoize(fun):
return wrapper
# http://code.activestate.com/recipes/577819-deprecated-decorator/
def deprecated(replacement=None):
"""A decorator which can be used to mark functions as deprecated."""
def outer(fun):
msg = "psutil.%s is deprecated" % fun.__name__
if replacement is not None:
msg += "; use %s instead" % replacement
if fun.__doc__ is None:
fun.__doc__ = msg
@wraps(fun)
def inner(*args, **kwargs):
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return fun(*args, **kwargs)
return inner
return outer
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.
"""
def outer(fun):
msg = "%s() is deprecated; use %s() instead" % (
fun.__name__, replacement)
if fun.__doc__ is None:
fun.__doc__ = msg
@wraps(fun)
def inner(self, *args, **kwargs):
warnings.warn(msg, category=DeprecationWarning, stacklevel=2)
return getattr(self, replacement)(*args, **kwargs)
return inner
return outer
def isfile_strict(path):
"""Same as os.path.isfile() but does not swallow EACCES / EPERM
exceptions, see:
@ -153,8 +132,7 @@ def isfile_strict(path):
"""
try:
st = os.stat(path)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in (errno.EPERM, errno.EACCES):
raise
return False
@ -162,6 +140,30 @@ def isfile_strict(path):
return stat.S_ISREG(st.st_mode)
def sockfam_to_enum(num):
"""Convert a numeric socket family value to an IntEnum member.
If it's not a known member, return the numeric value itself.
"""
if enum is None:
return num
try:
return socket.AddressFamily(num)
except (ValueError, AttributeError):
return num
def socktype_to_enum(num):
"""Convert a numeric socket type value to an IntEnum member.
If it's not a known member, return the numeric value itself.
"""
if enum is None:
return num
try:
return socket.AddressType(num)
except (ValueError, AttributeError):
return num
# --- Process.connections() 'kind' parameter mapping
conn_tmap = {
@ -186,7 +188,7 @@ if AF_UNIX is not None:
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
})
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
# --- namedtuples for psutil.* system-related functions
@ -212,6 +214,10 @@ suser = namedtuple('suser', ['name', 'terminal', 'host', 'started'])
# psutil.net_connections()
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status', 'pid'])
# psutil.net_if_addrs()
snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast'])
# psutil.net_if_stats()
snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu'])
# --- namedtuples for psutil.Process methods
@ -235,24 +241,6 @@ pio = namedtuple('pio', ['read_count', 'write_count',
pionice = namedtuple('pionice', ['ioclass', 'value'])
# psutil.Process.ctx_switches()
pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary'])
# --- misc
# backward compatibility layer for Process.connections() ntuple
class pconn(
namedtuple('pconn',
['fd', 'family', 'type', 'laddr', 'raddr', 'status'])):
__slots__ = ()
@property
def local_address(self):
warnings.warn("'local_address' field is deprecated; use 'laddr'"
"instead", category=DeprecationWarning, stacklevel=2)
return self.laddr
@property
def remote_address(self):
warnings.warn("'remote_address' field is deprecated; use 'raddr'"
"instead", category=DeprecationWarning, stacklevel=2)
return self.raddr
# psutil.Process.connections()
pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status'])

View File

@ -6,59 +6,29 @@
"""Module which provides compatibility with older Python versions."""
__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable", "namedtuple",
"property", "wraps", "defaultdict", "update_wrapper", "lru_cache"]
import collections
import functools
import sys
try:
import __builtin__
except ImportError:
import builtins as __builtin__ # py3
__all__ = ["PY3", "long", "xrange", "unicode", "callable", "lru_cache"]
PY3 = sys.version_info[0] == 3
if PY3:
int = int
long = int
xrange = range
unicode = str
basestring = str
exec_ = getattr(__builtin__, "exec")
print_ = getattr(__builtin__, "print")
def u(s):
return s
def b(s):
return s.encode("latin-1")
else:
int = int
long = long
xrange = xrange
unicode = unicode
basestring = basestring
def u(s):
return unicode(s, "unicode_escape")
def b(s):
return s
def exec_(code, globs=None, locs=None):
if globs is None:
frame = _sys._getframe(1)
globs = frame.f_globals
if locs is None:
locs = frame.f_locals
del frame
elif locs is None:
locs = globs
exec("""exec code in globs, locs""")
def print_(s):
sys.stdout.write(s + '\n')
sys.stdout.flush()
# removed in 3.0, reintroduced in 3.2
try:
@ -70,222 +40,6 @@ except NameError:
# --- stdlib additions
# py 2.6 collections.namedtuple
# Taken from: http://code.activestate.com/recipes/500261/
# Credits: Raymond Hettinger
try:
from collections import namedtuple
except ImportError:
from operator import itemgetter as _itemgetter
from keyword import iskeyword as _iskeyword
import sys as _sys
def namedtuple(typename, field_names, verbose=False, rename=False):
"""A collections.namedtuple implementation, see:
http://docs.python.org/library/collections.html#namedtuple
"""
if isinstance(field_names, basestring):
field_names = field_names.replace(',', ' ').split()
field_names = tuple(map(str, field_names))
if rename:
names = list(field_names)
seen = set()
for i, name in enumerate(names):
if ((not min(c.isalnum() or c == '_' for c in name)
or _iskeyword(name)
or not name or name[0].isdigit()
or name.startswith('_')
or name in seen)):
names[i] = '_%d' % i
seen.add(name)
field_names = tuple(names)
for name in (typename,) + field_names:
if not min(c.isalnum() or c == '_' for c in name):
raise ValueError('Type names and field names can only contain '
'alphanumeric characters and underscores: %r'
% name)
if _iskeyword(name):
raise ValueError('Type names and field names cannot be a '
'keyword: %r' % name)
if name[0].isdigit():
raise ValueError('Type names and field names cannot start '
'with a number: %r' % name)
seen_names = set()
for name in field_names:
if name.startswith('_') and not rename:
raise ValueError(
'Field names cannot start with an underscore: %r' % name)
if name in seen_names:
raise ValueError('Encountered duplicate field name: %r' % name)
seen_names.add(name)
numfields = len(field_names)
argtxt = repr(field_names).replace("'", "")[1:-1]
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
template = '''class %(typename)s(tuple):
'%(typename)s(%(argtxt)s)' \n
__slots__ = () \n
_fields = %(field_names)r \n
def __new__(_cls, %(argtxt)s):
return _tuple.__new__(_cls, (%(argtxt)s)) \n
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new %(typename)s object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != %(numfields)d:
raise TypeError(
'Expected %(numfields)d arguments, got %%d' %% len(result))
return result \n
def __repr__(self):
return '%(typename)s(%(reprtxt)s)' %% self \n
def _asdict(self):
'Return a new dict which maps field names to their values'
return dict(zip(self._fields, self)) \n
def _replace(_self, **kwds):
result = _self._make(map(kwds.pop, %(field_names)r, _self))
if kwds:
raise ValueError(
'Got unexpected field names: %%r' %% kwds.keys())
return result \n
def __getnewargs__(self):
return tuple(self) \n\n''' % locals()
for i, name in enumerate(field_names):
template += ' %s = _property(_itemgetter(%d))\n' % (name, i)
if verbose:
sys.stdout.write(template + '\n')
sys.stdout.flush()
namespace = dict(
_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
_property=property, _tuple=tuple)
try:
exec_(template, namespace)
except SyntaxError:
e = sys.exc_info()[1]
raise SyntaxError(e.message + ':\n' + template)
result = namespace[typename]
try:
result.__module__ = _sys._getframe(
1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return result
# hack to support property getter/setter/deleter on python < 2.6
# http://docs.python.org/library/functions.html?highlight=property#property
if hasattr(property, 'setter'):
property = property
else:
class property(__builtin__.property):
__metaclass__ = type
def __init__(self, fget, *args, **kwargs):
super(property, self).__init__(fget, *args, **kwargs)
self.__doc__ = fget.__doc__
def getter(self, method):
return property(method, self.fset, self.fdel)
def setter(self, method):
return property(self.fget, method, self.fdel)
def deleter(self, method):
return property(self.fget, self.fset, method)
# py 2.5 collections.defauldict
# Taken from:
# http://code.activestate.com/recipes/523034-emulate-collectionsdefaultdict/
# Credits: Jason Kirtland
try:
from collections import defaultdict
except ImportError:
class defaultdict(dict):
"""Dict subclass that calls a factory function to supply
missing values:
http://docs.python.org/library/collections.html#collections.defaultdict
"""
def __init__(self, default_factory=None, *a, **kw):
if ((default_factory is not None and
not hasattr(default_factory, '__call__'))):
raise TypeError('first argument must be callable')
dict.__init__(self, *a, **kw)
self.default_factory = default_factory
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
def __missing__(self, key):
if self.default_factory is None:
raise KeyError(key)
self[key] = value = self.default_factory()
return value
def __reduce__(self):
if self.default_factory is None:
args = tuple()
else:
args = self.default_factory,
return type(self), args, None, None, self.items()
def copy(self):
return self.__copy__()
def __copy__(self):
return type(self)(self.default_factory, self)
def __deepcopy__(self, memo):
import copy
return type(self)(self.default_factory,
copy.deepcopy(self.items()))
def __repr__(self):
return 'defaultdict(%s, %s)' % (self.default_factory,
dict.__repr__(self))
# py 2.5 functools.wraps
try:
from functools import wraps
except ImportError:
def wraps(original):
def inner(fn):
for attribute in ['__module__', '__name__', '__doc__']:
setattr(fn, attribute, getattr(original, attribute))
for attribute in ['__dict__']:
if hasattr(fn, attribute):
getattr(fn, attribute).update(getattr(original, attribute))
else:
setattr(fn, attribute,
getattr(original, attribute).copy())
return fn
return inner
# py 2.5 functools.update_wrapper
try:
from functools import update_wrapper
except ImportError:
WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS,
updated=WRAPPER_UPDATES):
"""Update a wrapper function to look like the wrapped function, see:
http://docs.python.org/library/functools.html#functools.update_wrapper
"""
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
return wrapper
# py 3.2 functools.lru_cache
# Taken from: http://code.activestate.com/recipes/578078
@ -298,8 +52,8 @@ except ImportError:
except ImportError:
from dummy_threading import RLock
_CacheInfo = namedtuple("CacheInfo",
["hits", "misses", "maxsize", "currsize"])
_CacheInfo = collections.namedtuple(
"CacheInfo", ["hits", "misses", "maxsize", "currsize"])
class _HashedSeq(list):
__slots__ = 'hashvalue'
@ -430,6 +184,6 @@ except ImportError:
wrapper.__wrapped__ = user_function
wrapper.cache_info = cache_info
wrapper.cache_clear = cache_clear
return update_wrapper(wrapper, user_function)
return functools.update_wrapper(wrapper, user_function)
return decorating_function

View File

@ -7,15 +7,17 @@
"""FreeBSD platform implementation."""
import errno
import functools
import os
import sys
import xml.etree.ElementTree as ET
from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import conn_tmap, usage_percent
from psutil._compat import namedtuple, wraps
import _psutil_bsd as cext
import _psutil_posix
from . import _common
from . import _psposix
from . import _psutil_bsd as cext
from . import _psutil_posix as cext_posix
from ._common import conn_tmap, usage_percent, sockfam_to_enum
from ._common import socktype_to_enum
__extra__all__ = []
@ -48,6 +50,7 @@ TCP_STATUSES = {
}
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
AF_LINK = cext_posix.AF_LINK
# extend base mem ntuple with BSD-specific memory metrics
svmem = namedtuple(
@ -63,12 +66,13 @@ pmmap_ext = namedtuple(
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
def virtual_memory():
"""System virtual memory as a namedutple."""
"""System virtual memory as a namedtuple."""
mem = cext.virtual_mem()
total, free, active, inactive, wired, cached, buffers, shared = mem
avail = inactive + cached + free
@ -86,14 +90,14 @@ def swap_memory():
def cpu_times():
"""Return system per-CPU times as a named tuple"""
"""Return system per-CPU times as a namedtuple"""
user, nice, system, idle, irq = cext.cpu_times()
return scputimes(user, nice, system, idle, irq)
if hasattr(cext, "per_cpu_times"):
def per_cpu_times():
"""Return system CPU times as a named tuple"""
"""Return system CPU times as a namedtuple"""
ret = []
for cpu_t in cext.per_cpu_times():
user, nice, system, idle, irq = cpu_t
@ -131,19 +135,25 @@ def cpu_count_physical():
# We may get None in case "sysctl kern.sched.topology_spec"
# is not supported on this BSD version, in which case we'll mimic
# os.cpu_count() and return None.
ret = None
s = cext.cpu_count_phys()
if s is not None:
# get rid of padding chars appended at the end of the string
index = s.rfind("</groups>")
if index != -1:
s = s[:index + 9]
if sys.version_info >= (2, 5):
import xml.etree.ElementTree as ET
root = ET.fromstring(s)
return len(root.findall('group/children/group/cpu')) or None
else:
s = s[s.find('<children>'):]
return s.count("<cpu") or None
root = ET.fromstring(s)
try:
ret = len(root.findall('group/children/group/cpu')) or None
finally:
# needed otherwise it will memleak
root.clear()
if not ret:
# If logical CPUs are 1 it's obvious we'll have only 1
# physical CPU.
if cpu_count_logical() == 1:
return 1
return ret
def boot_time():
@ -183,15 +193,36 @@ def net_connections(kind):
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
ret = []
ret = set()
rawlist = cext.net_connections()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
# TODO: apply filter at C level
if fam in families and type in types:
status = TCP_STATUSES[status]
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]
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
ret.append(nt)
ret.add(nt)
return list(ret)
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
names = net_io_counters().keys()
ret = {}
for name in names:
isup, duplex, speed, mtu = cext_posix.net_if_stats(name)
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
@ -200,23 +231,27 @@ pid_exists = _psposix.pid_exists
disk_usage = _psposix.disk_usage
net_io_counters = cext.net_io_counters
disk_io_counters = cext.disk_io_counters
net_if_addrs = cext_posix.net_if_addrs
def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
"""
@wraps(fun)
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
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
@ -226,11 +261,12 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name"]
__slots__ = ["pid", "_name", "_ppid"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
@wrap_exceptions
def name(self):
@ -312,6 +348,8 @@ class Process(object):
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
fam = sockfam_to_enum(fam)
type = socktype_to_enum(type)
status = TCP_STATUSES[status]
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.append(nt)
@ -329,11 +367,11 @@ class Process(object):
@wrap_exceptions
def nice_get(self):
return _psutil_posix.getpriority(self.pid)
return cext_posix.getpriority(self.pid)
@wrap_exceptions
def nice_set(self, value):
return _psutil_posix.setpriority(self.pid, value)
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def status(self):
@ -387,3 +425,31 @@ class Process(object):
proc_cwd = _not_implemented
memory_maps = _not_implemented
num_fds = _not_implemented
@wrap_exceptions
def cpu_affinity_get(self):
return cext.proc_cpu_affinity_get(self.pid)
@wrap_exceptions
def cpu_affinity_set(self, cpus):
# Pre-emptively check if CPUs are valid because the C
# function has a weird behavior in case of invalid CPUs,
# see: https://github.com/giampaolo/psutil/issues/586
allcpus = tuple(range(len(per_cpu_times())))
for cpu in cpus:
if cpu not in allcpus:
raise ValueError("invalid CPU #%i (choose between %s)"
% (cpu, allcpus))
try:
cext.proc_cpu_affinity_set(self.pid, cpus)
except OSError as err:
# 'man cpuset_setaffinity' about EDEADLK:
# <<the call would leave a thread without a valid CPU to run
# on because the set does not overlap with the thread's
# anonymous mask>>
if err.errno in (errno.EINVAL, errno.EDEADLK):
for cpu in cpus:
if cpu not in allcpus:
raise ValueError("invalid CPU #%i (choose between %s)"
% (cpu, allcpus))
raise

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,16 @@
"""OSX platform implementation."""
import errno
import functools
import os
import sys
from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import conn_tmap, usage_percent, isfile_strict
from psutil._compat import namedtuple, wraps
import _psutil_osx as cext
import _psutil_posix
from . import _common
from . import _psposix
from . import _psutil_osx as cext
from . import _psutil_posix as cext_posix
from ._common import conn_tmap, usage_percent, isfile_strict
from ._common import sockfam_to_enum, socktype_to_enum
__extra__all__ = []
@ -23,6 +24,7 @@ __extra__all__ = []
# --- constants
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
AF_LINK = cext_posix.AF_LINK
# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
TCP_STATUSES = {
@ -65,6 +67,7 @@ pmmap_ext = namedtuple(
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
@ -165,28 +168,44 @@ def net_connections(kind='inet'):
return ret
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
names = net_io_counters().keys()
ret = {}
for name in names:
isup, duplex, speed, mtu = cext_posix.net_if_stats(name)
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
pids = cext.pids
pid_exists = _psposix.pid_exists
disk_usage = _psposix.disk_usage
net_io_counters = cext.net_io_counters
disk_io_counters = cext.disk_io_counters
net_if_addrs = cext_posix.net_if_addrs
def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
NoSuchProcess and AccessDenied.
"""
@wraps(fun)
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
raise
err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._name)
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
@ -196,11 +215,12 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name"]
__slots__ = ["pid", "_name", "_ppid"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
@wrap_exceptions
def name(self):
@ -293,6 +313,8 @@ class Process(object):
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)
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.append(nt)
return ret
@ -315,11 +337,11 @@ class Process(object):
@wrap_exceptions
def nice_get(self):
return _psutil_posix.getpriority(self.pid)
return cext_posix.getpriority(self.pid)
@wrap_exceptions
def nice_set(self, value):
return _psutil_posix.setpriority(self.pid, value)
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def status(self):

View File

@ -12,8 +12,8 @@ import os
import sys
import time
from psutil._common import sdiskusage, usage_percent, memoize
from psutil._compat import PY3, unicode
from ._common import sdiskusage, usage_percent, memoize
from ._compat import PY3, unicode
class TimeoutExpired(Exception):
@ -31,8 +31,7 @@ def pid_exists(pid):
return True
try:
os.kill(pid, 0)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
@ -69,17 +68,18 @@ def wait_pid(pid, timeout=None):
timer = getattr(time, 'monotonic', time.time)
if timeout is not None:
waitcall = lambda: os.waitpid(pid, os.WNOHANG)
def waitcall():
return os.waitpid(pid, os.WNOHANG)
stop_at = timer() + timeout
else:
waitcall = lambda: os.waitpid(pid, 0)
def waitcall():
return os.waitpid(pid, 0)
delay = 0.0001
while 1:
while True:
try:
retpid, status = waitcall()
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.EINTR:
delay = check_timeout(delay)
continue
@ -90,7 +90,7 @@ def wait_pid(pid, timeout=None):
# - 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 1:
while True:
if pid_exists(pid):
delay = check_timeout(delay)
else:
@ -150,8 +150,7 @@ def _get_terminal_map():
assert name not in ret
try:
ret[os.stat(name).st_rdev] = name
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno != errno.ENOENT:
raise
return ret

View File

@ -11,18 +11,21 @@ import os
import socket
import subprocess
import sys
from collections import namedtuple
from psutil import _common
from psutil import _psposix
from psutil._common import usage_percent, isfile_strict
from psutil._compat import namedtuple, PY3
import _psutil_posix
import _psutil_sunos as cext
from . import _common
from . import _psposix
from . import _psutil_posix as cext_posix
from . import _psutil_sunos as cext
from ._common import isfile_strict, socktype_to_enum, sockfam_to_enum
from ._common import usage_percent
from ._compat import PY3
__extra__all__ = ["CONN_IDLE", "CONN_BOUND"]
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
AF_LINK = cext_posix.AF_LINK
CONN_IDLE = "IDLE"
CONN_BOUND = "BOUND"
@ -63,6 +66,7 @@ pmmap_ext = namedtuple(
# set later from __init__.py
NoSuchProcess = None
ZombieProcess = None
AccessDenied = None
TimeoutExpired = None
@ -71,6 +75,7 @@ TimeoutExpired = None
disk_io_counters = cext.disk_io_counters
net_io_counters = cext.net_io_counters
disk_usage = _psposix.disk_usage
net_if_addrs = cext_posix.net_if_addrs
def virtual_memory():
@ -91,7 +96,9 @@ def swap_memory():
# usr/src/cmd/swap/swap.c
# ...nevertheless I can't manage to obtain the same numbers as 'swap'
# cmdline utility, so let's parse its output (sigh!)
p = subprocess.Popen(['swap', '-l', '-k'], stdout=subprocess.PIPE)
p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' %
os.environ['PATH'], 'swap', '-l', '-k'],
stdout=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout = stdout.decode(sys.stdout.encoding)
@ -209,7 +216,7 @@ 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, families, types)
ret = []
ret = set()
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
if fam not in families:
@ -217,11 +224,24 @@ def net_connections(kind, _pid=-1):
if type_ not in types:
continue
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)
ret.append(nt)
ret.add(nt)
return list(ret)
def net_if_stats():
"""Get NIC stats (isup, duplex, speed, mtu)."""
ret = cext.net_if_stats()
for name, items in ret.items():
isup, duplex, speed, mtu = items
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
@ -232,16 +252,19 @@ def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except EnvironmentError:
except EnvironmentError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
if (NoSuchProcess is None or AccessDenied is None or
ZombieProcess is None):
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.
err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
raise NoSuchProcess(self.pid, self._name)
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
@ -251,11 +274,12 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name"]
__slots__ = ["pid", "_name", "_ppid"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
@wrap_exceptions
def name(self):
@ -292,10 +316,11 @@ class Process(object):
# Note: tested on Solaris 11; on Open Solaris 5 everything is
# fine.
try:
return _psutil_posix.getpriority(self.pid)
except EnvironmentError:
err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
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
@ -308,7 +333,7 @@ class Process(object):
# The process actually exists though, as it has a name,
# creation time, etc.
raise AccessDenied(self.pid, self._name)
return _psutil_posix.setpriority(self.pid, value)
return cext_posix.setpriority(self.pid, value)
@wrap_exceptions
def ppid(self):
@ -338,8 +363,7 @@ class Process(object):
for x in (0, 1, 2, 255):
try:
return os.readlink('/proc/%d/path/%d' % (self.pid, x))
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@ -356,8 +380,7 @@ class Process(object):
# Reference: http://goo.gl/55XgO
try:
return os.readlink("/proc/%s/path/cwd" % self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.ENOENT:
os.stat("/proc/%s" % self.pid)
return None
@ -388,9 +411,8 @@ class Process(object):
try:
utime, stime = cext.query_process_thread(
self.pid, tid)
except EnvironmentError:
except EnvironmentError as err:
# ENOENT == thread gone in meantime
err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@ -413,9 +435,8 @@ class Process(object):
if os.path.islink(path):
try:
file = os.readlink(path)
except OSError:
except OSError as err:
# ENOENT == file which is gone in the meantime
err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
hit_enoent = True
continue
@ -495,8 +516,7 @@ class Process(object):
if not name.startswith('['):
try:
name = os.readlink('/proc/%s/path/%s' % (self.pid, name))
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.ENOENT:
# sometimes the link may not be resolved by
# readlink() even if it exists (ls shows it).

View File

@ -21,12 +21,14 @@
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/cpuset.h>
#include <net/route.h>
#include <sys/socket.h>
#include <sys/socketvar.h> // for struct xsocket
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/sockio.h>
// for xinpcb struct
#include <netinet/in.h>
#include <netinet/in_systm.h>
@ -49,6 +51,7 @@
#include <net/if.h> // net io counters
#include <net/if_dl.h>
#include <net/route.h>
#include <net/if_media.h>
#include <netinet/in.h> // process open files/connections
#include <sys/un.h>
@ -91,6 +94,18 @@ psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc)
}
/*
* Set exception to AccessDenied if pid exists else NoSuchProcess.
*/
void
psutil_raise_ad_or_nsp(long pid) {
if (psutil_pid_exists(pid) == 0)
NoSuchProcess();
else
AccessDenied();
}
/*
* Return a Python list of all the PIDs running on the system.
*/
@ -104,9 +119,8 @@ psutil_pids(PyObject *self, PyObject *args)
PyObject *retlist = PyList_New(0);
PyObject *pid = NULL;
if (retlist == NULL) {
if (retlist == NULL)
return NULL;
}
if (psutil_get_proc_list(&proclist, &num_processes) != 0) {
PyErr_SetString(PyExc_RuntimeError,
"failed to retrieve process list.");
@ -132,9 +146,8 @@ psutil_pids(PyObject *self, PyObject *args)
error:
Py_XDECREF(pid);
Py_DECREF(retlist);
if (orig_address != NULL) {
if (orig_address != NULL)
free(orig_address);
}
return NULL;
}
@ -167,12 +180,10 @@ psutil_proc_name(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("s", kp.ki_comm);
}
@ -191,9 +202,8 @@ psutil_proc_exe(PyObject *self, PyObject *args)
int mib[4];
size_t size;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@ -207,12 +217,10 @@ psutil_proc_exe(PyObject *self, PyObject *args)
return NULL;
}
if (size == 0 || strlen(pathname) == 0) {
if (psutil_pid_exists(pid) == 0) {
if (psutil_pid_exists(pid) == 0)
return NoSuchProcess();
}
else {
else
strcpy(pathname, "");
}
}
return Py_BuildValue("s", pathname);
}
@ -227,18 +235,16 @@ psutil_proc_cmdline(PyObject *self, PyObject *args)
long pid;
PyObject *arglist = NULL;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
// get the commandline, defined in arch/bsd/process_info.c
arglist = psutil_get_arg_list(pid);
// psutil_get_arg_list() returns NULL only if psutil_cmd_args
// failed with ESRCH (no process with that PID)
if (NULL == arglist) {
if (NULL == arglist)
return PyErr_SetFromErrno(PyExc_OSError);
}
return Py_BuildValue("N", arglist);
}
@ -251,12 +257,10 @@ psutil_proc_ppid(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("l", (long)kp.ki_ppid);
}
@ -269,12 +273,10 @@ psutil_proc_status(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("i", (int)kp.ki_stat);
}
@ -288,12 +290,10 @@ psutil_proc_uids(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("lll",
(long)kp.ki_ruid,
(long)kp.ki_uid,
@ -310,12 +310,10 @@ psutil_proc_gids(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("lll",
(long)kp.ki_rgid,
(long)kp.ki_groups[0],
@ -332,12 +330,10 @@ psutil_proc_tty_nr(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("i", kp.ki_tdev);
}
@ -350,12 +346,10 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("(ll)",
kp.ki_rusage.ru_nvcsw,
kp.ki_rusage.ru_nivcsw);
@ -370,12 +364,10 @@ psutil_proc_num_threads(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("l", (long)kp.ki_numthreads);
}
@ -456,9 +448,8 @@ psutil_proc_threads(PyObject *self, PyObject *args)
error:
Py_XDECREF(pyTuple);
Py_DECREF(retList);
if (kip != NULL) {
if (kip != NULL)
free(kip);
}
return NULL;
}
@ -472,12 +463,10 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args)
long pid;
double user_t, sys_t;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
// convert from microseconds to seconds
user_t = TV2DOUBLE(kp.ki_rusage.ru_utime);
sys_t = TV2DOUBLE(kp.ki_rusage.ru_stime);
@ -500,14 +489,10 @@ psutil_cpu_count_logical(PyObject *self, PyObject *args)
mib[1] = HW_NCPU;
len = sizeof(ncpu);
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
// mimic os.cpu_count()
Py_INCREF(Py_None);
return Py_None;
}
else {
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
Py_RETURN_NONE; // mimic os.cpu_count()
else
return Py_BuildValue("i", ncpu);
}
}
@ -520,6 +505,7 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
{
void *topology = NULL;
size_t size = 0;
PyObject *py_str;
if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0))
goto error;
@ -533,11 +519,14 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0))
goto error;
return Py_BuildValue("s", topology);
py_str = Py_BuildValue("s", topology);
free(topology);
return py_str;
error:
Py_INCREF(Py_None);
return Py_None;
if (topology != NULL)
free(topology);
Py_RETURN_NONE;
}
@ -550,12 +539,10 @@ psutil_proc_create_time(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("d", TV2DOUBLE(kp.ki_start));
}
@ -569,12 +556,10 @@ psutil_proc_io_counters(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
// there's apparently no way to determine bytes count, hence return -1.
return Py_BuildValue("(llll)",
kp.ki_rusage.ru_inblock,
@ -592,12 +577,10 @@ psutil_proc_memory_info(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("(lllll)",
ptoa(kp.ki_rssize), // rss
(long)kp.ki_size, // vms
@ -749,7 +732,10 @@ psutil_cpu_times(PyObject *self, PyObject *args)
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
/*
* Return files opened by process as a list of (path, fd) tuples
* Return files opened by process as a list of (path, fd) tuples.
* TODO: this is broken as it may report empty paths. 'procstat'
* utility has the same problem see:
* https://github.com/giampaolo/psutil/issues/595
*/
static PyObject *
psutil_proc_open_files(PyObject *self, PyObject *args)
@ -867,9 +853,8 @@ psutil_proc_cwd(PyObject *self, PyObject *args)
* (lsof can't do that it either). Since this happens even
* as root we return an empty string instead of AccessDenied.
*/
if (path == NULL) {
if (path == NULL)
path = Py_BuildValue("s", "");
}
free(freep);
return path;
@ -887,7 +872,6 @@ psutil_fetch_tcplist(void)
{
char *buf;
size_t len;
int error;
for (;;) {
if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) {
@ -917,7 +901,8 @@ psutil_sockaddr_port(int family, struct sockaddr_storage *ss)
if (family == AF_INET) {
sin = (struct sockaddr_in *)ss;
return (sin->sin_port);
} else {
}
else {
sin6 = (struct sockaddr_in6 *)ss;
return (sin6->sin6_port);
}
@ -932,7 +917,8 @@ psutil_sockaddr_addr(int family, struct sockaddr_storage *ss)
if (family == AF_INET) {
sin = (struct sockaddr_in *)ss;
return (&sin->sin_addr);
} else {
}
else {
sin6 = (struct sockaddr_in6 *)ss;
return (&sin6->sin6_addr);
}
@ -1030,12 +1016,10 @@ psutil_proc_connections(PyObject *self, PyObject *args)
PyObject *_family = NULL;
PyObject *_type = NULL;
if (retList == NULL) {
if (retList == NULL)
return NULL;
}
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter))
goto error;
}
if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
@ -1063,22 +1047,18 @@ psutil_proc_connections(PyObject *self, PyObject *args)
raddr = NULL;
kif = &freep[i];
if (kif->kf_type == KF_TYPE_SOCKET)
{
if (kif->kf_type == KF_TYPE_SOCKET) {
// apply filters
_family = PyLong_FromLong((long)kif->kf_sock_domain);
inseq = PySequence_Contains(af_filter, _family);
Py_DECREF(_family);
if (inseq == 0) {
if (inseq == 0)
continue;
}
_type = PyLong_FromLong((long)kif->kf_sock_type);
inseq = PySequence_Contains(type_filter, _type);
Py_DECREF(_type);
if (inseq == 0) {
if (inseq == 0)
continue;
}
// IPv4 / IPv6 socket
if ((kif->kf_sock_domain == AF_INET) ||
(kif->kf_sock_domain == AF_INET6)) {
@ -1112,12 +1092,10 @@ psutil_proc_connections(PyObject *self, PyObject *args)
laddr = Py_BuildValue("(si)", lip, lport);
if (!laddr)
goto error;
if (rport != 0) {
if (rport != 0)
raddr = Py_BuildValue("(si)", rip, rport);
}
else {
else
raddr = Py_BuildValue("()");
}
if (!raddr)
goto error;
tuple = Py_BuildValue("(iiiNNi)",
@ -1140,7 +1118,7 @@ psutil_proc_connections(PyObject *self, PyObject *args)
sun = (struct sockaddr_un *)&kif->kf_sa_local;
snprintf(
path, sizeof(path), "%.*s",
(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
sun->sun_path);
tuple = Py_BuildValue("(iiisOi)",
@ -1250,7 +1228,7 @@ void remove_spaces(char *str) {
do
while (*p2 == ' ')
p2++;
while (*p1++ = *p2++);
while ((*p1++ = *p2++));
}
@ -1264,7 +1242,7 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
long pid;
int ptrwidth;
int i, cnt;
char addr[30];
char addr[1000];
char perms[4];
const char *path;
struct kinfo_proc kp;
@ -1274,15 +1252,12 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
PyObject *pytuple = NULL;
PyObject *retlist = PyList_New(0);
if (retlist == NULL) {
if (retlist == NULL)
return NULL;
}
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
}
if (psutil_kinfo_proc(pid, &kp) == -1) {
if (psutil_kinfo_proc(pid, &kp) == -1)
goto error;
}
freep = kinfo_getvmmap(pid, &cnt);
if (freep == NULL) {
@ -1306,36 +1281,36 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
if (strlen(kve->kve_path) == 0) {
switch (kve->kve_type) {
case KVME_TYPE_NONE:
path = "[none]";
break;
case KVME_TYPE_DEFAULT:
path = "[default]";
break;
case KVME_TYPE_VNODE:
path = "[vnode]";
break;
case KVME_TYPE_SWAP:
path = "[swap]";
break;
case KVME_TYPE_DEVICE:
path = "[device]";
break;
case KVME_TYPE_PHYS:
path = "[phys]";
break;
case KVME_TYPE_DEAD:
path = "[dead]";
break;
case KVME_TYPE_SG:
path = "[sg]";
break;
case KVME_TYPE_UNKNOWN:
path = "[unknown]";
break;
default:
path = "[?]";
break;
case KVME_TYPE_NONE:
path = "[none]";
break;
case KVME_TYPE_DEFAULT:
path = "[default]";
break;
case KVME_TYPE_VNODE:
path = "[vnode]";
break;
case KVME_TYPE_SWAP:
path = "[swap]";
break;
case KVME_TYPE_DEVICE:
path = "[device]";
break;
case KVME_TYPE_PHYS:
path = "[phys]";
break;
case KVME_TYPE_DEAD:
path = "[dead]";
break;
case KVME_TYPE_SG:
path = "[sg]";
break;
case KVME_TYPE_UNKNOWN:
path = "[unknown]";
break;
default:
path = "[?]";
break;
}
}
else {
@ -1489,9 +1464,9 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
size_t len;
PyObject *py_retdict = PyDict_New();
PyObject *py_ifc_info = NULL;
if (py_retdict == NULL)
return NULL;
mib[0] = CTL_NET; // networking subsystem
mib[1] = PF_ROUTE; // type of information
mib[2] = 0; // protocol (IPPROTO_xxx)
@ -1533,9 +1508,8 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
// http://lists.freebsd.org/pipermail/freebsd-current/
// 2011-October/028752.html
// 'ifconfig -a' doesn't show them, nor do we.
if (strncmp(ifc_name, "usbus", 5) == 0) {
if (strncmp(ifc_name, "usbus", 5) == 0)
continue;
}
py_ifc_info = Py_BuildValue("(kkkkkkki)",
if2m->ifm_data.ifi_obytes,
@ -1580,9 +1554,9 @@ psutil_disk_io_counters(PyObject *self, PyObject *args)
PyObject *py_retdict = PyDict_New();
PyObject *py_disk_info = NULL;
if (py_retdict == NULL)
return NULL;
if (devstat_checkversion(NULL) < 0) {
PyErr_Format(PyExc_RuntimeError, "devstat_checkversion() failed");
goto error;
@ -1626,9 +1600,8 @@ psutil_disk_io_counters(PyObject *self, PyObject *args)
Py_DECREF(py_disk_info);
}
if (stats.dinfo->mem_ptr) {
if (stats.dinfo->mem_ptr)
free(stats.dinfo->mem_ptr);
}
free(stats.dinfo);
return py_retdict;
@ -1766,14 +1739,16 @@ psutil_get_pid_from_sock(int sock_hash)
if (xf->xf_data == NULL)
continue;
hash = (int)((uintptr_t)xf->xf_data % HASHSIZE);
if (sock_hash == hash) {
if (sock_hash == hash)
return xf->xf_pid;
}
}
return -1;
}
// Reference:
// https://gitorious.org/freebsd/freebsd/source/
// f1d6f4778d2044502209708bc167c05f9aa48615:usr.bin/sockstat/sockstat.c
int psutil_gather_inet(int proto, PyObject *py_retlist)
{
struct xinpgen *xig, *exig;
@ -1781,25 +1756,26 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
struct xtcpcb *xtp;
struct inpcb *inp;
struct xsocket *so;
struct sock *sock;
const char *varname;
const char *varname = NULL;
size_t len, bufsize;
void *buf;
int hash, retry, vflag, type;
int hash;
int retry;
int type;
PyObject *tuple = NULL;
PyObject *laddr = NULL;
PyObject *raddr = NULL;
switch (proto) {
case IPPROTO_TCP:
varname = "net.inet.tcp.pcblist";
type = SOCK_STREAM;
break;
case IPPROTO_UDP:
varname = "net.inet.udp.pcblist";
type = SOCK_DGRAM;
break;
case IPPROTO_TCP:
varname = "net.inet.tcp.pcblist";
type = SOCK_STREAM;
break;
case IPPROTO_UDP:
varname = "net.inet.udp.pcblist";
type = SOCK_DGRAM;
break;
}
buf = NULL;
@ -1808,10 +1784,8 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
do {
for (;;) {
buf = realloc(buf, bufsize);
if (buf == NULL) {
// XXX
continue;
}
if (buf == NULL)
continue; // XXX
len = bufsize;
if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
break;
@ -1831,33 +1805,41 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
for (;;) {
int lport, rport, pid, status, family;
xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len);
if (xig >= exig)
break;
switch (proto) {
case IPPROTO_TCP:
xtp = (struct xtcpcb *)xig;
if (xtp->xt_len != sizeof *xtp) {
PyErr_Format(PyExc_RuntimeError, "struct xtcpcb size mismatch");
case IPPROTO_TCP:
xtp = (struct xtcpcb *)xig;
if (xtp->xt_len != sizeof *xtp) {
PyErr_Format(PyExc_RuntimeError,
"struct xtcpcb size mismatch");
goto error;
}
inp = &xtp->xt_inp;
so = &xtp->xt_socket;
status = xtp->xt_tp.t_state;
break;
case IPPROTO_UDP:
xip = (struct xinpcb *)xig;
if (xip->xi_len != sizeof *xip) {
PyErr_Format(PyExc_RuntimeError,
"struct xinpcb size mismatch");
goto error;
}
inp = &xip->xi_inp;
so = &xip->xi_socket;
status = PSUTIL_CONN_NONE;
break;
default:
PyErr_Format(PyExc_RuntimeError, "invalid proto");
goto error;
}
break;
case IPPROTO_UDP:
xip = (struct xinpcb *)xig;
if (xip->xi_len != sizeof *xip) {
PyErr_Format(PyExc_RuntimeError, "struct xinpcb size mismatch");
goto error;
}
inp = &xip->xi_inp;
so = &xip->xi_socket;
break;
}
inp = &xtp->xt_inp;
so = &xtp->xt_socket;
char lip[200], rip[200];
int family, lport, rport, pid, status;
hash = (int)((uintptr_t)so->xso_so % HASHSIZE);
pid = psutil_get_pid_from_sock(hash);
@ -1865,7 +1847,6 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
continue;
lport = ntohs(inp->inp_lport);
rport = ntohs(inp->inp_fport);
status = xtp->xt_tp.t_state;
if (inp->inp_vflag & INP_IPV4) {
family = AF_INET;
@ -1882,12 +1863,10 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
laddr = Py_BuildValue("(si)", lip, lport);
if (!laddr)
goto error;
if (rport != 0) {
if (rport != 0)
raddr = Py_BuildValue("(si)", rip, rport);
}
else {
else
raddr = Py_BuildValue("()");
}
if (!raddr)
goto error;
tuple = Py_BuildValue("(iiiNNii)", -1, family, type, laddr, raddr,
@ -1897,7 +1876,7 @@ int psutil_gather_inet(int proto, PyObject *py_retlist)
if (PyList_Append(py_retlist, tuple))
goto error;
Py_DECREF(tuple);
}
}
free(buf);
return 1;
@ -1915,12 +1894,14 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
{
struct xunpgen *xug, *exug;
struct xunpcb *xup;
struct sock *sock;
const char *varname, *protoname;
size_t len, bufsize;
const char *varname = NULL;
const char *protoname = NULL;
size_t len;
size_t bufsize;
void *buf;
int hash, retry;
int family, lport, rport, pid;
int hash;
int retry;
int pid;
struct sockaddr_un *sun;
char path[PATH_MAX];
@ -1929,14 +1910,14 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
PyObject *raddr = NULL;
switch (proto) {
case SOCK_STREAM:
varname = "net.local.stream.pcblist";
protoname = "stream";
break;
case SOCK_DGRAM:
varname = "net.local.dgram.pcblist";
protoname = "dgram";
break;
case SOCK_STREAM:
varname = "net.local.stream.pcblist";
protoname = "stream";
break;
case SOCK_DGRAM:
varname = "net.local.dgram.pcblist";
protoname = "dgram";
break;
}
buf = NULL;
@ -1973,10 +1954,8 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
if (xug >= exug)
break;
xup = (struct xunpcb *)xug;
if (xup->xu_len != sizeof *xup) {
warnx("struct xunpgen size mismatch");
if (xup->xu_len != sizeof *xup)
goto error;
}
hash = (int)((uintptr_t) xup->xu_socket.xso_so % HASHSIZE);
pid = psutil_get_pid_from_sock(hash);
@ -1985,7 +1964,7 @@ int psutil_gather_unix(int proto, PyObject *py_retlist)
sun = (struct sockaddr_un *)&xup->xu_addr;
snprintf(path, sizeof(path), "%.*s",
(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
sun->sun_path);
tuple = Py_BuildValue("(iiisOii)", -1, AF_UNIX, proto, path, Py_None,
@ -2016,13 +1995,12 @@ error:
static PyObject*
psutil_net_connections(PyObject* self, PyObject* args)
{
PyObject *af_filter = NULL;
PyObject *type_filter = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
if (psutil_populate_xfiles() != 1)
goto error;
if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0)
goto error;
if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0)
@ -2042,6 +2020,107 @@ error:
}
/*
* Get process CPU affinity.
* Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
*/
static PyObject*
psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args)
{
long pid;
int ret;
int i;
cpuset_t mask;
PyObject* py_retlist;
PyObject* py_cpu_num;
if (!PyArg_ParseTuple(args, "i", &pid))
return NULL;
ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
sizeof(mask), &mask);
if (ret != 0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
py_retlist = PyList_New(0);
if (py_retlist == NULL)
return NULL;
for (i = 0; i < CPU_SETSIZE; i++) {
if (CPU_ISSET(i, &mask)) {
py_cpu_num = Py_BuildValue("i", i);
if (py_cpu_num == NULL)
goto error;
if (PyList_Append(py_retlist, py_cpu_num))
goto error;
}
}
return py_retlist;
error:
Py_XDECREF(py_cpu_num);
Py_DECREF(py_retlist);
return NULL;
}
/*
* Set process CPU affinity.
* Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c
*/
static PyObject *
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
{
long pid;
int i;
int seq_len;
int ret;
cpuset_t cpu_set;
PyObject *py_cpu_set;
PyObject *py_cpu_seq = NULL;
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
return NULL;
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");
if (!py_cpu_seq)
return NULL;
seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq);
// calculate the mask
CPU_ZERO(&cpu_set);
for (i = 0; i < seq_len; i++) {
PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i);
#if PY_MAJOR_VERSION >= 3
long value = PyLong_AsLong(item);
#else
long value = PyInt_AsLong(item);
#endif
if (value == -1 && PyErr_Occurred())
goto error;
CPU_SET(value, &cpu_set);
}
// set affinity
ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid,
sizeof(cpu_set), &cpu_set);
if (ret != 0) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
Py_DECREF(py_cpu_seq);
Py_RETURN_NONE;
error:
if (py_cpu_seq != NULL)
Py_DECREF(py_cpu_seq);
return NULL;
}
/*
* define the psutil C module methods and initialize the module.
*/
@ -2083,6 +2162,10 @@ PsutilMethods[] =
"Return process IO counters"},
{"proc_tty_nr", psutil_proc_tty_nr, METH_VARARGS,
"Return process tty (terminal) number"},
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
"Return process CPU affinity."},
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
"Set process CPU affinity."},
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
{"proc_open_files", psutil_proc_open_files, METH_VARARGS,
"Return files opened by process as a list of (path, fd) tuples"},
@ -2181,6 +2264,8 @@ void init_psutil_bsd(void)
#else
PyObject *module = Py_InitModule("_psutil_bsd", PsutilMethods);
#endif
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
// process status constants
PyModule_AddIntConstant(module, "SSTOP", SSTOP);
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
@ -2203,9 +2288,8 @@ void init_psutil_bsd(void)
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
if (module == NULL) {
if (module == NULL)
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif

View File

@ -26,6 +26,8 @@ static PyObject* psutil_proc_status(PyObject* self, PyObject* args);
static PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_tty_nr(PyObject* self, PyObject* args);
static PyObject* psutil_proc_uids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
@ -48,4 +50,4 @@ static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
#endif
#endif

View File

@ -19,6 +19,11 @@
#include <linux/version.h>
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/sockios.h>
#include <linux/if.h>
#include <linux/ethtool.h>
#include "_psutil_linux.h"
@ -46,6 +51,12 @@ enum {
IOPRIO_WHO_PROCESS = 1,
};
// May happen on old RedHat versions, see:
// https://github.com/giampaolo/psutil/issues/607
#ifndef DUPLEX_UNKNOWN
#define DUPLEX_UNKNOWN 0xff
#endif
static inline int
ioprio_get(int which, int who)
{
@ -74,13 +85,11 @@ psutil_proc_ioprio_get(PyObject *self, PyObject *args)
{
long pid;
int ioprio, ioclass, iodata;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
if (ioprio == -1) {
if (ioprio == -1)
return PyErr_SetFromErrno(PyExc_OSError);
}
ioclass = IOPRIO_PRIO_CLASS(ioprio);
iodata = IOPRIO_PRIO_DATA(ioprio);
return Py_BuildValue("ii", ioclass, iodata);
@ -99,16 +108,13 @@ psutil_proc_ioprio_set(PyObject *self, PyObject *args)
int ioprio, ioclass, iodata;
int retval;
if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata)) {
if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata))
return NULL;
}
ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata);
retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio);
if (retval == -1) {
if (retval == -1)
return PyErr_SetFromErrno(PyExc_OSError);
}
Py_INCREF(Py_None);
return Py_None;
Py_RETURN_NONE;
}
#endif
@ -129,9 +135,8 @@ psutil_linux_prlimit(PyObject *self, PyObject *args)
PyObject *soft = NULL;
PyObject *hard = NULL;
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard)) {
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard))
return NULL;
}
// get
if (soft == NULL && hard == NULL) {
@ -169,8 +174,7 @@ psutil_linux_prlimit(PyObject *self, PyObject *args)
ret = prlimit(pid, resource, newp, &old);
if (ret == -1)
return PyErr_SetFromErrno(PyExc_OSError);
Py_INCREF(Py_None);
return Py_None;
Py_RETURN_NONE;
}
}
#endif
@ -235,10 +239,9 @@ static PyObject *
psutil_linux_sysinfo(PyObject *self, PyObject *args)
{
struct sysinfo info;
if (sysinfo(&info) != 0) {
return PyErr_SetFromErrno(PyExc_OSError);
}
if (sysinfo(&info) != 0)
return PyErr_SetFromErrno(PyExc_OSError);
// note: boot time might also be determined from here
return Py_BuildValue(
"(KKKKKK)",
@ -268,10 +271,8 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
cpu_set_t *mask = NULL;
PyObject *res = NULL;
if (!PyArg_ParseTuple(args, "i", &pid)) {
if (!PyArg_ParseTuple(args, "i", &pid))
return NULL;
}
ncpus = NCPUS_START;
while (1) {
setsize = CPU_ALLOC_SIZE(ncpus);
@ -303,7 +304,6 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
#else
PyObject *cpu_num = PyInt_FromLong(cpu);
#endif
--count;
if (cpu_num == NULL)
goto error;
if (PyList_Append(res, cpu_num)) {
@ -311,6 +311,7 @@ psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
goto error;
}
Py_DECREF(cpu_num);
--count;
}
}
CPU_FREE(mask);
@ -325,33 +326,45 @@ error:
#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* ret_list;
int i;
PyObject* py_retlist = NULL;
PyObject *py_cpu_num = NULL;
if (!PyArg_ParseTuple(args, "i", &pid)) {
if (!PyArg_ParseTuple(args, "i", &pid))
return NULL;
}
CPU_ZERO(&cpuset);
if (sched_getaffinity(pid, len, &cpuset) < 0) {
if (sched_getaffinity(pid, len, &cpuset) < 0)
return PyErr_SetFromErrno(PyExc_OSError);
}
ret_list = PyList_New(0);
py_retlist = PyList_New(0);
if (py_retlist == NULL)
goto error;
for (i = 0; i < CPU_SETSIZE; ++i) {
if (CPU_ISSET(i, &cpuset)) {
PyList_Append(ret_list, Py_BuildValue("i", i));
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 ret_list;
return py_retlist;
error:
Py_XDECREF(py_cpu_num);
Py_DECREF(py_retlist);
return NULL;
}
#endif
@ -368,22 +381,18 @@ 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)) {
goto error;
}
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set))
return NULL;
if (!PySequence_Check(py_cpu_set)) {
// does not work on Python 2.4
// PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
// Py_TYPE(py_cpu_set)->tp_name);
PyErr_Format(PyExc_TypeError, "sequence argument expected");
PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s",
Py_TYPE(py_cpu_set)->tp_name);
goto error;
}
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");
if (!py_cpu_seq) {
if (!py_cpu_seq)
goto error;
}
seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq);
CPU_ZERO(&cpu_set);
for (i = 0; i < seq_len; i++) {
@ -393,9 +402,8 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
#else
long value = PyInt_AsLong(item);
#endif
if (value == -1 && PyErr_Occurred()) {
if (value == -1 && PyErr_Occurred())
goto error;
}
CPU_SET(value, &cpu_set);
}
@ -406,14 +414,11 @@ psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
}
Py_DECREF(py_cpu_seq);
Py_INCREF(Py_None);
return Py_None;
Py_RETURN_NONE;
error:
if (py_cpu_seq != NULL) {
if (py_cpu_seq != NULL)
Py_DECREF(py_cpu_seq);
}
return NULL;
}
@ -465,6 +470,87 @@ error:
}
/*
* Return stats about a particular network
* interface. References:
* https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py
* http://www.i-scream.org/libstatgrab/
*/
static PyObject*
psutil_net_if_stats(PyObject* self, PyObject* args)
{
char *nic_name;
int sock = 0;
int ret;
int duplex;
int speed;
int mtu;
struct ifreq ifr;
struct ethtool_cmd ethcmd;
PyObject *py_is_up = NULL;
PyObject *py_ret = NULL;
if (! PyArg_ParseTuple(args, "s", &nic_name))
return NULL;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
// is up?
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
if (ret == -1)
goto error;
if ((ifr.ifr_flags & IFF_UP) != 0)
py_is_up = Py_True;
else
py_is_up = Py_False;
Py_INCREF(py_is_up);
// MTU
ret = ioctl(sock, SIOCGIFMTU, &ifr);
if (ret == -1)
goto error;
mtu = ifr.ifr_mtu;
// duplex and speed
memset(&ethcmd, 0, sizeof ethcmd);
ethcmd.cmd = ETHTOOL_GSET;
ifr.ifr_data = (caddr_t)&ethcmd;
ret = ioctl(sock, SIOCETHTOOL, &ifr);
if (ret != -1) {
duplex = ethcmd.duplex;
speed = ethcmd.speed;
}
else {
if (errno == EOPNOTSUPP) {
// we typically get here in case of wi-fi cards
duplex = DUPLEX_UNKNOWN;
speed = 0;
}
else {
goto error;
}
}
close(sock);
py_ret = Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu);
if (!py_ret)
goto error;
Py_DECREF(py_is_up);
return py_ret;
error:
Py_XDECREF(py_is_up);
if (sock != 0)
close(sock);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
/*
* Define the psutil C module methods and initialize the module.
*/
@ -491,6 +577,8 @@ PsutilMethods[] =
"device, mount point and filesystem type"},
{"users", psutil_users, METH_VARARGS,
"Return currently connected users as a list of tuples"},
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats (isup, duplex, speed, mtu)"},
// --- linux specific
@ -559,6 +647,7 @@ void init_psutil_linux(void)
#endif
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
#if PSUTIL_HAVE_PRLIMIT
PyModule_AddIntConstant(module, "RLIM_INFINITY", RLIM_INFINITY);
PyModule_AddIntConstant(module, "RLIMIT_AS", RLIMIT_AS);
@ -588,10 +677,12 @@ void init_psutil_linux(void)
PyModule_AddIntConstant(module, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING);
#endif
#endif
PyModule_AddIntConstant(module, "DUPLEX_HALF", DUPLEX_HALF);
PyModule_AddIntConstant(module, "DUPLEX_FULL", DUPLEX_FULL);
PyModule_AddIntConstant(module, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN);
if (module == NULL) {
if (module == NULL)
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif

View File

@ -18,3 +18,4 @@ static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_linux_sysinfo(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);

View File

@ -120,12 +120,10 @@ psutil_proc_name(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("s", kp.kp_proc.p_comm);
}
@ -139,9 +137,8 @@ psutil_proc_cwd(PyObject *self, PyObject *args)
long pid;
struct proc_vnodepathinfo pathinfo;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (! psutil_proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, &pathinfo,
sizeof(pathinfo)))
@ -162,17 +159,14 @@ psutil_proc_exe(PyObject *self, PyObject *args)
char buf[PATH_MAX];
int ret;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
ret = proc_pidpath(pid, &buf, sizeof(buf));
if (ret == 0) {
if (! psutil_pid_exists(pid)) {
if (! psutil_pid_exists(pid))
return NoSuchProcess();
}
else {
else
return AccessDenied();
}
}
return Py_BuildValue("s", buf);
}
@ -187,9 +181,8 @@ psutil_proc_cmdline(PyObject *self, PyObject *args)
long pid;
PyObject *arglist = NULL;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
// get the commandline, defined in arch/osx/process_info.c
arglist = psutil_get_arg_list(pid);
@ -205,12 +198,10 @@ psutil_proc_ppid(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("l", (long)kp.kp_eproc.e_ppid);
}
@ -223,12 +214,10 @@ psutil_proc_uids(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("lll",
(long)kp.kp_eproc.e_pcred.p_ruid,
(long)kp.kp_eproc.e_ucred.cr_uid,
@ -244,12 +233,10 @@ psutil_proc_gids(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("lll",
(long)kp.kp_eproc.e_pcred.p_rgid,
(long)kp.kp_eproc.e_ucred.cr_groups[0],
@ -265,12 +252,10 @@ psutil_proc_tty_nr(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("i", kp.kp_eproc.e_tdev);
}
@ -299,9 +284,8 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
if (py_list == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
}
err = task_for_pid(mach_task_self(), pid, &task);
@ -324,11 +308,8 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
err = vm_region_recurse_64(task, &address, &size, &depth,
(vm_region_info_64_t)&info, &count);
if (err == KERN_INVALID_ADDRESS) {
if (err == KERN_INVALID_ADDRESS)
break;
}
if (info.is_submap) {
depth++;
}
@ -356,32 +337,30 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
if (strlen(buf) == 0) {
switch (info.share_mode) {
/*
case SM_LARGE_PAGE:
// Treat SM_LARGE_PAGE the same as SM_PRIVATE
// since they are not shareable and are wired.
*/
case SM_COW:
strcpy(buf, "[cow]");
break;
case SM_PRIVATE:
strcpy(buf, "[prv]");
break;
case SM_EMPTY:
strcpy(buf, "[nul]");
break;
case SM_SHARED:
case SM_TRUESHARED:
strcpy(buf, "[shm]");
break;
case SM_PRIVATE_ALIASED:
strcpy(buf, "[ali]");
break;
case SM_SHARED_ALIASED:
strcpy(buf, "[s/a]");
break;
default:
strcpy(buf, "[???]");
// case SM_LARGE_PAGE:
// Treat SM_LARGE_PAGE the same as SM_PRIVATE
// since they are not shareable and are wired.
case SM_COW:
strcpy(buf, "[cow]");
break;
case SM_PRIVATE:
strcpy(buf, "[prv]");
break;
case SM_EMPTY:
strcpy(buf, "[nul]");
break;
case SM_SHARED:
case SM_TRUESHARED:
strcpy(buf, "[shm]");
break;
case SM_PRIVATE_ALIASED:
strcpy(buf, "[ali]");
break;
case SM_SHARED_ALIASED:
strcpy(buf, "[s/a]");
break;
default:
strcpy(buf, "[???]");
}
}
@ -432,19 +411,14 @@ psutil_cpu_count_logical(PyObject *self, PyObject *args)
int mib[2];
int ncpu;
size_t len;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(ncpu);
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) {
// mimic os.cpu_count()
Py_INCREF(Py_None);
return Py_None;
}
else {
if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1)
Py_RETURN_NONE; // mimic os.cpu_count()
else
return Py_BuildValue("i", ncpu);
}
}
@ -456,12 +430,11 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
{
int num;
size_t size = sizeof(int);
if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0)) {
// mimic os.cpu_count()
Py_INCREF(Py_None);
return Py_None;
}
return Py_BuildValue("i", num);
if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0))
Py_RETURN_NONE; // mimic os.cpu_count()
else
return Py_BuildValue("i", num);
}
@ -475,12 +448,11 @@ psutil_proc_cpu_times(PyObject *self, PyObject *args)
{
long pid;
struct proc_taskinfo pti;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
return NULL;
}
return Py_BuildValue("(dd)",
(float)pti.pti_total_user / 1000000000.0,
(float)pti.pti_total_system / 1000000000.0);
@ -496,12 +468,10 @@ psutil_proc_create_time(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("d", TV2DOUBLE(kp.kp_proc.p_starttime));
}
@ -514,13 +484,11 @@ psutil_proc_memory_info(PyObject *self, PyObject *args)
{
long pid;
struct proc_taskinfo pti;
if (! PyArg_ParseTuple(args, "l", &pid)) {
return NULL;
}
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
return NULL;
}
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
return NULL;
// Note: determining other memory stats on OSX is a mess:
// http://www.opensource.apple.com/source/top/top-67/libtop.c?txt
// I just give up...
@ -544,12 +512,11 @@ psutil_proc_num_threads(PyObject *self, PyObject *args)
{
long pid;
struct proc_taskinfo pti;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
return NULL;
}
return Py_BuildValue("k", pti.pti_threadnum);
}
@ -562,12 +529,11 @@ psutil_proc_num_ctx_switches(PyObject *self, PyObject *args)
{
long pid;
struct proc_taskinfo pti;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) {
if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti)))
return NULL;
}
// unvoluntary value seems not to be available;
// pti.pti_csw probably refers to the sum of the two (getrusage()
// numbers seems to confirm this theory).
@ -587,10 +553,10 @@ psutil_virtual_mem(PyObject *self, PyObject *args)
size_t len = sizeof(total);
vm_statistics_data_t vm;
int pagesize = getpagesize();
// physical mem
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
if (sysctl(mib, 2, &total, &len, NULL, 0)) {
if (errno != 0)
PyErr_SetFromErrno(PyExc_OSError);
@ -600,9 +566,8 @@ psutil_virtual_mem(PyObject *self, PyObject *args)
}
// vm
if (!psutil_sys_vminfo(&vm)) {
if (!psutil_sys_vminfo(&vm))
return NULL;
}
return Py_BuildValue(
"KKKKK",
@ -637,9 +602,8 @@ psutil_swap_mem(PyObject *self, PyObject *args)
PyErr_Format(PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) failed");
return NULL;
}
if (!psutil_sys_vminfo(&vmstat)) {
if (!psutil_sys_vminfo(&vmstat))
return NULL;
}
return Py_BuildValue(
"LLLKK",
@ -664,11 +628,10 @@ psutil_cpu_times(PyObject *self, PyObject *args)
mach_port_t host_port = mach_host_self();
error = host_statistics(host_port, HOST_CPU_LOAD_INFO,
(host_info_t)&r_load, &count);
if (error != KERN_SUCCESS) {
if (error != KERN_SUCCESS)
return PyErr_Format(PyExc_RuntimeError,
"Error in host_statistics(): %s",
mach_error_string(error));
}
mach_port_deallocate(mach_task_self(), host_port);
return Py_BuildValue(
@ -728,9 +691,8 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
info_count * sizeof(int));
if (ret != KERN_SUCCESS) {
if (ret != KERN_SUCCESS)
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
}
return py_retlist;
error:
@ -739,9 +701,8 @@ error:
if (cpu_load_info != NULL) {
ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array,
info_count * sizeof(int));
if (ret != KERN_SUCCESS) {
if (ret != KERN_SUCCESS)
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
}
}
return NULL;
}
@ -900,12 +861,10 @@ psutil_proc_status(PyObject *self, PyObject *args)
{
long pid;
struct kinfo_proc kp;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
if (psutil_get_kinfo_proc(pid, &kp) == -1)
return NULL;
}
return Py_BuildValue("i", (int)kp.kp_proc.p_stat);
}
@ -934,19 +893,16 @@ psutil_proc_threads(PyObject *self, PyObject *args)
return NULL;
// the argument passed should be a process id
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
}
// task_for_pid() requires special privileges
err = task_for_pid(mach_task_self(), pid, &task);
if (err != KERN_SUCCESS) {
if (! psutil_pid_exists(pid)) {
if (! psutil_pid_exists(pid))
NoSuchProcess();
}
else {
else
AccessDenied();
}
goto error;
}
@ -999,9 +955,8 @@ psutil_proc_threads(PyObject *self, PyObject *args)
ret = vm_deallocate(task, (vm_address_t)thread_list,
thread_count * sizeof(int));
if (ret != KERN_SUCCESS) {
if (ret != KERN_SUCCESS)
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
}
mach_port_deallocate(mach_task_self(), task);
@ -1015,9 +970,8 @@ error:
if (thread_list != NULL) {
ret = vm_deallocate(task, (vm_address_t)thread_list,
thread_count * sizeof(int));
if (ret != KERN_SUCCESS) {
if (ret != KERN_SUCCESS)
PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2);
}
}
return NULL;
}
@ -1048,9 +1002,8 @@ psutil_proc_open_files(PyObject *self, PyObject *args)
if (retList == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
goto error;
}
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
if (pidinfo_result <= 0) {
@ -1127,19 +1080,14 @@ psutil_proc_open_files(PyObject *self, PyObject *args)
error:
Py_XDECREF(tuple);
Py_DECREF(retList);
if (fds_pointer != NULL) {
if (fds_pointer != NULL)
free(fds_pointer);
}
if (errno != 0) {
if (errno != 0)
return PyErr_SetFromErrno(PyExc_OSError);
}
else if (! psutil_pid_exists(pid)) {
else if (! psutil_pid_exists(pid))
return NoSuchProcess();
}
else {
// exception has already been set earlier
return NULL;
}
else
return NULL; // exception has already been set earlier
}
@ -1175,23 +1123,19 @@ psutil_proc_connections(PyObject *self, PyObject *args)
if (retList == NULL)
return NULL;
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter))
goto error;
}
if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) {
PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence");
goto error;
}
if (pid == 0) {
if (pid == 0)
return retList;
}
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
if (pidinfo_result <= 0) {
if (pidinfo_result <= 0)
goto error;
}
fds_pointer = malloc(pidinfo_result);
if (fds_pointer == NULL) {
@ -1201,10 +1145,8 @@ psutil_proc_connections(PyObject *self, PyObject *args)
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
pidinfo_result);
if (pidinfo_result <= 0) {
if (pidinfo_result <= 0)
goto error;
}
iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE);
for (i = 0; i < iterations; i++) {
@ -1225,14 +1167,12 @@ psutil_proc_connections(PyObject *self, PyObject *args)
// let's assume socket has been closed
continue;
}
if (errno != 0) {
if (errno != 0)
PyErr_SetFromErrno(PyExc_OSError);
}
else {
else
PyErr_Format(
PyExc_RuntimeError,
"proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed");
}
goto error;
}
if (nb < sizeof(si)) {
@ -1258,15 +1198,13 @@ psutil_proc_connections(PyObject *self, PyObject *args)
_family = PyLong_FromLong((long)family);
inseq = PySequence_Contains(af_filter, _family);
Py_DECREF(_family);
if (inseq == 0) {
if (inseq == 0)
continue;
}
_type = PyLong_FromLong((long)type);
inseq = PySequence_Contains(type_filter, _type);
Py_DECREF(_type);
if (inseq == 0) {
if (inseq == 0)
continue;
}
if (errno != 0) {
PyErr_SetFromErrno(PyExc_OSError);
@ -1305,22 +1243,18 @@ psutil_proc_connections(PyObject *self, PyObject *args)
lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport);
rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport);
if (type == SOCK_STREAM) {
if (type == SOCK_STREAM)
state = (int)si.psi.soi_proto.pri_tcp.tcpsi_state;
}
else {
else
state = PSUTIL_CONN_NONE;
}
laddr = Py_BuildValue("(si)", lip, lport);
if (!laddr)
goto error;
if (rport != 0) {
if (rport != 0)
raddr = Py_BuildValue("(si)", rip, rport);
}
else {
else
raddr = Py_BuildValue("()");
}
if (!raddr)
goto error;
@ -1359,19 +1293,15 @@ error:
Py_XDECREF(raddr);
Py_DECREF(retList);
if (fds_pointer != NULL) {
if (fds_pointer != NULL)
free(fds_pointer);
}
if (errno != 0) {
if (errno != 0)
return PyErr_SetFromErrno(PyExc_OSError);
}
else if (! psutil_pid_exists(pid) ) {
else if (! psutil_pid_exists(pid))
return NoSuchProcess();
}
else {
else
return PyErr_Format(PyExc_RuntimeError,
"proc_pidinfo(PROC_PIDLISTFDS) failed");
}
}
@ -1386,19 +1316,16 @@ psutil_proc_num_fds(PyObject *self, PyObject *args)
int num;
struct proc_fdinfo *fds_pointer;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
if (pidinfo_result <= 0) {
if (pidinfo_result <= 0)
return PyErr_SetFromErrno(PyExc_OSError);
}
fds_pointer = malloc(pidinfo_result);
if (fds_pointer == NULL) {
if (fds_pointer == NULL)
return PyErr_NoMemory();
}
pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer,
pidinfo_result);
if (pidinfo_result <= 0) {
@ -1851,6 +1778,7 @@ init_psutil_osx(void)
#else
PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods);
#endif
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
// 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);
@ -1872,9 +1800,8 @@ init_psutil_osx(void)
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
if (module == NULL) {
if (module == NULL)
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif

View File

@ -10,6 +10,24 @@
#include <errno.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#ifdef __linux
#include <netdb.h>
#include <linux/if_packet.h>
#endif // end linux
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <netdb.h>
#include <netinet/in.h>
#include <net/if_dl.h>
#endif
#if defined(__sun)
#include <netdb.h>
#endif
#include "_psutil_posix.h"
@ -23,13 +41,12 @@ psutil_posix_getpriority(PyObject *self, PyObject *args)
long pid;
int priority;
errno = 0;
if (! PyArg_ParseTuple(args, "l", &pid)) {
if (! PyArg_ParseTuple(args, "l", &pid))
return NULL;
}
priority = getpriority(PRIO_PROCESS, pid);
if (errno != 0) {
if (errno != 0)
return PyErr_SetFromErrno(PyExc_OSError);
}
return Py_BuildValue("i", priority);
}
@ -43,18 +60,394 @@ psutil_posix_setpriority(PyObject *self, PyObject *args)
long pid;
int priority;
int retval;
if (! PyArg_ParseTuple(args, "li", &pid, &priority)) {
if (! PyArg_ParseTuple(args, "li", &pid, &priority))
return NULL;
}
retval = setpriority(PRIO_PROCESS, pid, priority);
if (retval == -1) {
if (retval == -1)
return PyErr_SetFromErrno(PyExc_OSError);
}
Py_INCREF(Py_None);
return Py_None;
Py_RETURN_NONE;
}
/*
* Translate a sockaddr struct into a Python string.
* Return None if address family is not AF_INET* or AF_PACKET.
*/
static PyObject *
psutil_convert_ipaddr(struct sockaddr *addr, int family)
{
char buf[NI_MAXHOST];
int err;
int addrlen;
int n;
size_t len;
const char *data;
char *ptr;
if (addr == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
else if (family == AF_INET || family == AF_INET6) {
if (family == AF_INET)
addrlen = sizeof(struct sockaddr_in);
else
addrlen = sizeof(struct sockaddr_in6);
err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
NI_NUMERICHOST);
if (err != 0) {
// 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;
Py_INCREF(Py_None);
return Py_None;
}
else {
return Py_BuildValue("s", buf);
}
}
#ifdef __linux
else if (family == AF_PACKET) {
struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr;
len = lladdr->sll_halen;
data = (const char *)lladdr->sll_addr;
}
#endif
#if defined(__FreeBSD__) || defined(__APPLE__)
else if (addr->sa_family == AF_LINK) {
// Note: prior to Python 3.4 socket module does not expose
// AF_LINK so we'll do.
struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr;
len = dladdr->sdl_alen;
data = LLADDR(dladdr);
}
#endif
else {
// unknown family
Py_INCREF(Py_None);
return Py_None;
}
// AF_PACKET or AF_LINK
if (len > 0) {
ptr = buf;
for (n = 0; n < len; ++n) {
sprintf(ptr, "%02x:", data[n] & 0xff);
ptr += 3;
}
*--ptr = '\0';
return Py_BuildValue("s", buf);
}
else {
Py_INCREF(Py_None);
return Py_None;
}
}
/*
* Return NICs information a-la ifconfig as a list of tuples.
* TODO: on Solaris we won't get any MAC address.
*/
static PyObject*
psutil_net_if_addrs(PyObject* self, PyObject* args)
{
struct ifaddrs *ifaddr, *ifa;
int family;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
PyObject *py_address = NULL;
PyObject *py_netmask = NULL;
PyObject *py_broadcast = NULL;
if (py_retlist == NULL)
return NULL;
if (getifaddrs(&ifaddr) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
continue;
family = ifa->ifa_addr->sa_family;
py_address = psutil_convert_ipaddr(ifa->ifa_addr, family);
// If the primary address can't be determined just skip it.
// I've never seen this happen on Linux but I did on FreeBSD.
if (py_address == Py_None)
continue;
if (py_address == NULL)
goto error;
py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family);
if (py_netmask == NULL)
goto error;
#ifdef __linux
py_broadcast = psutil_convert_ipaddr(ifa->ifa_ifu.ifu_broadaddr, family);
#else
py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
#endif
if (py_broadcast == NULL)
goto error;
py_tuple = Py_BuildValue(
"(siOOO)",
ifa->ifa_name,
family,
py_address,
py_netmask,
py_broadcast
);
if (! py_tuple)
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);
}
freeifaddrs(ifaddr);
return py_retlist;
error:
if (ifaddr != NULL)
freeifaddrs(ifaddr);
Py_DECREF(py_retlist);
Py_XDECREF(py_tuple);
Py_XDECREF(py_address);
Py_XDECREF(py_netmask);
Py_XDECREF(py_broadcast);
return NULL;
}
/*
* net_if_stats() implementation. This is here because it is common
* to both OSX and FreeBSD and I didn't know where else to put it.
*/
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <sys/sockio.h>
#include <net/if_media.h>
#include <net/if.h>
int psutil_get_nic_speed(int ifm_active) {
// Determine NIC speed. Taken from:
// http://www.i-scream.org/libstatgrab/
// Assuming only ETHER devices
switch(IFM_TYPE(ifm_active)) {
case IFM_ETHER:
switch(IFM_SUBTYPE(ifm_active)) {
#if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \
|| (IFM_10G_LR != IFM_HPNA_1))
// HomePNA 1.0 (1Mb/s)
case(IFM_HPNA_1):
return 1;
#endif
// 10 Mbit
case(IFM_10_T): // 10BaseT - RJ45
case(IFM_10_2): // 10Base2 - Thinnet
case(IFM_10_5): // 10Base5 - AUI
case(IFM_10_STP): // 10BaseT over shielded TP
case(IFM_10_FL): // 10baseFL - Fiber
return 10;
// 100 Mbit
case(IFM_100_TX): // 100BaseTX - RJ45
case(IFM_100_FX): // 100BaseFX - Fiber
case(IFM_100_T4): // 100BaseT4 - 4 pair cat 3
case(IFM_100_VG): // 100VG-AnyLAN
case(IFM_100_T2): // 100BaseT2
return 100;
// 1000 Mbit
case(IFM_1000_SX): // 1000BaseSX - multi-mode fiber
case(IFM_1000_LX): // 1000baseLX - single-mode fiber
case(IFM_1000_CX): // 1000baseCX - 150ohm STP
#if defined(IFM_1000_TX) && !defined(OPENBSD)
// FreeBSD 4 and others (but NOT OpenBSD)?
case(IFM_1000_TX):
#endif
#ifdef IFM_1000_FX
case(IFM_1000_FX):
#endif
#ifdef IFM_1000_T
case(IFM_1000_T):
#endif
return 1000;
#if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \
|| defined(IFM_10G_T)
#ifdef IFM_10G_SR
case(IFM_10G_SR):
#endif
#ifdef IFM_10G_LR
case(IFM_10G_LR):
#endif
#ifdef IFM_10G_CX4
case(IFM_10G_CX4):
#endif
#ifdef IFM_10G_TWINAX
case(IFM_10G_TWINAX):
#endif
#ifdef IFM_10G_TWINAX_LONG
case(IFM_10G_TWINAX_LONG):
#endif
#ifdef IFM_10G_T
case(IFM_10G_T):
#endif
return 10000;
#endif
#if defined(IFM_2500_SX)
#ifdef IFM_2500_SX
case(IFM_2500_SX):
#endif
return 2500;
#endif // any 2.5GBit stuff...
// We don't know what it is
default:
return 0;
}
break;
#ifdef IFM_TOKEN
case IFM_TOKEN:
switch(IFM_SUBTYPE(ifm_active)) {
case IFM_TOK_STP4: // Shielded twisted pair 4m - DB9
case IFM_TOK_UTP4: // Unshielded twisted pair 4m - RJ45
return 4;
case IFM_TOK_STP16: // Shielded twisted pair 16m - DB9
case IFM_TOK_UTP16: // Unshielded twisted pair 16m - RJ45
return 16;
#if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100)
#ifdef IFM_TOK_STP100
case IFM_TOK_STP100: // Shielded twisted pair 100m - DB9
#endif
#ifdef IFM_TOK_UTP100
case IFM_TOK_UTP100: // Unshielded twisted pair 100m - RJ45
#endif
return 100;
#endif
// We don't know what it is
default:
return 0;
}
break;
#endif
#ifdef IFM_FDDI
case IFM_FDDI:
switch(IFM_SUBTYPE(ifm_active)) {
// We don't know what it is
default:
return 0;
}
break;
#endif
case IFM_IEEE80211:
switch(IFM_SUBTYPE(ifm_active)) {
case IFM_IEEE80211_FH1: // Frequency Hopping 1Mbps
case IFM_IEEE80211_DS1: // Direct Sequence 1Mbps
return 1;
case IFM_IEEE80211_FH2: // Frequency Hopping 2Mbps
case IFM_IEEE80211_DS2: // Direct Sequence 2Mbps
return 2;
case IFM_IEEE80211_DS5: // Direct Sequence 5Mbps
return 5;
case IFM_IEEE80211_DS11: // Direct Sequence 11Mbps
return 11;
case IFM_IEEE80211_DS22: // Direct Sequence 22Mbps
return 22;
// We don't know what it is
default:
return 0;
}
break;
default:
return 0;
}
}
/*
* Return stats about a particular network interface.
* References:
* http://www.i-scream.org/libstatgrab/
*/
static PyObject *
psutil_net_if_stats(PyObject *self, PyObject *args)
{
char *nic_name;
int sock = 0;
int ret;
int duplex;
int speed;
int mtu;
struct ifreq ifr;
struct ifmediareq ifmed;
PyObject *py_is_up = NULL;
if (! PyArg_ParseTuple(args, "s", &nic_name))
return NULL;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;
strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
// is up?
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
if (ret == -1)
goto error;
if ((ifr.ifr_flags & IFF_UP) != 0)
py_is_up = Py_True;
else
py_is_up = Py_False;
Py_INCREF(py_is_up);
// MTU
ret = ioctl(sock, SIOCGIFMTU, &ifr);
if (ret == -1)
goto error;
mtu = ifr.ifr_mtu;
// speed / duplex
memset(&ifmed, 0, sizeof(struct ifmediareq));
strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name));
ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed);
if (ret == -1) {
speed = 0;
duplex = 0;
}
else {
speed = psutil_get_nic_speed(ifmed.ifm_active);
if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active)
duplex = 2;
else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active)
duplex = 1;
else
duplex = 0;
}
close(sock);
Py_DECREF(py_is_up);
return Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu);
error:
Py_XDECREF(py_is_up);
if (sock != 0)
close(sock);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
#endif // net_if_stats() implementation
/*
* define the psutil C module methods and initialize the module.
*/
@ -65,6 +458,12 @@ PsutilMethods[] =
"Return process priority"},
{"setpriority", psutil_posix_setpriority, METH_VARARGS,
"Set process priority"},
{"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
"Retrieve NICs information"},
#if defined(__FreeBSD__) || defined(__APPLE__)
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats."},
#endif
{NULL, NULL, 0, NULL}
};
@ -119,9 +518,13 @@ void init_psutil_posix(void)
#else
PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods);
#endif
if (module == NULL) {
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__sun)
PyModule_AddIntConstant(module, "AF_LINK", AF_LINK);
#endif
if (module == NULL)
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif

View File

@ -6,5 +6,10 @@
#include <Python.h>
static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args);
static PyObject* psutil_posix_getpriority(PyObject* self, PyObject* args);
static PyObject* psutil_posix_setpriority(PyObject* self, PyObject* args);
#if defined(__FreeBSD__) || defined(__APPLE__)
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
#endif

View File

@ -30,6 +30,8 @@
#include <sys/mntent.h> // for MNTTAB
#include <sys/mnttab.h>
#include <sys/procfs.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <utmpx.h>
#include <kstat.h>
@ -38,6 +40,7 @@
#include <stropts.h>
#include <inet/tcp.h>
#include <arpa/inet.h>
#include <net/if.h>
#include "_psutil_sunos.h"
@ -201,13 +204,11 @@ proc_io_counters(PyObject* self, PyObject* args)
char path[100];
prusage_t info;
if (! PyArg_ParseTuple(args, "i", &pid)) {
if (! PyArg_ParseTuple(args, "i", &pid))
return NULL;
}
sprintf(path, "/proc/%i/usage", pid);
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) {
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
}
// On Solaris we only have 'pr_ioch' which accounts for bytes read
// *and* written.
@ -315,9 +316,8 @@ psutil_swap_mem(PyObject *self, PyObject *args)
uint_t sout = 0;
kc = kstat_open();
if (kc == NULL) {
if (kc == NULL)
return PyErr_SetFromErrno(PyExc_OSError);;
}
k = kc->kc_chain;
while (k != NULL) {
@ -442,8 +442,6 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
kstat_ctl_t *kc;
kstat_t *ksp;
cpu_stat_t cs;
int numcpus;
int i;
PyObject *py_retlist = PyList_New(0);
PyObject *py_cputime = NULL;
@ -456,29 +454,24 @@ psutil_per_cpu_times(PyObject *self, PyObject *args)
goto error;
}
numcpus = sysconf(_SC_NPROCESSORS_ONLN) - 1;
for (i = 0; i <= numcpus; i++) {
ksp = kstat_lookup(kc, "cpu_stat", i, NULL);
if (ksp == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
if (strcmp(ksp->ks_module, "cpu_stat") == 0) {
if (kstat_read(kc, ksp, &cs) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
py_cputime = Py_BuildValue("ffff",
(float)cs.cpu_sysinfo.cpu[CPU_USER],
(float)cs.cpu_sysinfo.cpu[CPU_KERNEL],
(float)cs.cpu_sysinfo.cpu[CPU_IDLE],
(float)cs.cpu_sysinfo.cpu[CPU_WAIT]);
if (py_cputime == NULL)
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
py_cputime = NULL;
}
if (kstat_read(kc, ksp, &cs) == -1) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
py_cputime = Py_BuildValue("ffff",
(float)cs.cpu_sysinfo.cpu[CPU_USER],
(float)cs.cpu_sysinfo.cpu[CPU_KERNEL],
(float)cs.cpu_sysinfo.cpu[CPU_IDLE],
(float)cs.cpu_sysinfo.cpu[CPU_WAIT]);
if (py_cputime == NULL)
goto error;
if (PyList_Append(py_retlist, py_cputime))
goto error;
Py_DECREF(py_cputime);
}
kstat_close(kc);
@ -576,17 +569,14 @@ psutil_proc_memory_maps(PyObject *self, PyObject *args)
PyObject *pytuple = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL) {
if (py_retlist == NULL)
return NULL;
}
if (! PyArg_ParseTuple(args, "i", &pid)) {
if (! PyArg_ParseTuple(args, "i", &pid))
goto error;
}
sprintf(path, "/proc/%i/status", pid);
if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) {
if (! psutil_file_to_struct(path, (void *)&status, sizeof(status)))
goto error;
}
sprintf(path, "/proc/%i/xmap", pid);
if (stat(path, &st) == -1) {
@ -722,9 +712,8 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
(strcmp(ksp->ks_module, "lo") != 0)) {
goto skip;
*/
if ((strcmp(ksp->ks_module, "link") != 0)) {
if ((strcmp(ksp->ks_module, "link") != 0))
goto next;
}
if (kstat_read(kc, ksp, NULL) == -1) {
errno = 0;
@ -747,18 +736,18 @@ psutil_net_io_counters(PyObject *self, PyObject *args)
#if defined(_INT64_TYPE)
py_ifc_info = Py_BuildValue("(KKKKkkii)",
rbytes->value.ui64,
wbytes->value.ui64,
rpkts->value.ui64,
rbytes->value.ui64,
wpkts->value.ui64,
rpkts->value.ui64,
ierrs->value.ui32,
oerrs->value.ui32,
#else
py_ifc_info = Py_BuildValue("(kkkkkkii)",
rbytes->value.ui32,
wbytes->value.ui32,
rpkts->value.ui32,
rbytes->value.ui32,
wpkts->value.ui32,
rpkts->value.ui32,
ierrs->value.ui32,
oerrs->value.ui32,
#endif
@ -810,7 +799,7 @@ static PyObject *
psutil_net_connections(PyObject *self, PyObject *args)
{
long pid;
int sd = NULL;
int sd = 0;
mib2_tcpConnEntry_t *tp = NULL;
mib2_udpEntry_t *ude;
#if defined(AF_INET6)
@ -822,6 +811,7 @@ psutil_net_connections(PyObject *self, PyObject *args)
char lip[200], rip[200];
int lport, rport;
int processed_pid;
int databuf_init = 0;
struct strbuf ctlbuf, databuf;
struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
@ -922,6 +912,7 @@ psutil_net_connections(PyObject *self, PyObject *args)
PyErr_NoMemory();
goto error;
}
databuf_init = 1;
flags = 0;
getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags);
@ -948,9 +939,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
py_laddr = Py_BuildValue("(si)", lip, lport);
if (!py_laddr)
goto error;
if (rport != 0) {
if (rport != 0)
py_raddr = Py_BuildValue("(si)", rip, rport);
}
else {
py_raddr = Py_BuildValue("()");
}
@ -962,9 +952,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM,
py_laddr, py_raddr, state,
processed_pid);
if (!py_tuple) {
if (!py_tuple)
goto error;
}
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
@ -991,12 +980,10 @@ psutil_net_connections(PyObject *self, PyObject *args)
py_laddr = Py_BuildValue("(si)", lip, lport);
if (!py_laddr)
goto error;
if (rport != 0) {
if (rport != 0)
py_raddr = Py_BuildValue("(si)", rip, rport);
}
else {
else
py_raddr = Py_BuildValue("()");
}
if (!py_raddr)
goto error;
state = tp6->tcp6ConnEntryInfo.ce_state;
@ -1004,9 +991,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
// add item
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM,
py_laddr, py_raddr, state, processed_pid);
if (!py_tuple) {
if (!py_tuple)
goto error;
}
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
@ -1039,9 +1025,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM,
py_laddr, py_raddr, PSUTIL_CONN_NONE,
processed_pid);
if (!py_tuple) {
if (!py_tuple)
goto error;
}
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
@ -1049,7 +1034,9 @@ psutil_net_connections(PyObject *self, PyObject *args)
}
#if defined(AF_INET6)
// UDPv6
else if (mibhdr->level == MIB2_UDP6 || mibhdr->level == MIB2_UDP6_ENTRY) {
else if (mibhdr->level == MIB2_UDP6 ||
mibhdr->level == MIB2_UDP6_ENTRY)
{
ude6 = (mib2_udp6Entry_t *)databuf.buf;
num_ent = mibhdr->len / sizeof(mib2_udp6Entry_t);
for (i = 0; i < num_ent; i++, ude6++) {
@ -1067,9 +1054,8 @@ psutil_net_connections(PyObject *self, PyObject *args)
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM,
py_laddr, py_raddr, PSUTIL_CONN_NONE,
processed_pid);
if (!py_tuple) {
if (!py_tuple)
goto error;
}
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);
@ -1087,8 +1073,9 @@ error:
Py_XDECREF(py_laddr);
Py_XDECREF(py_raddr);
Py_DECREF(py_retlist);
// TODO : free databuf
if (sd != NULL)
if (databuf_init == 1)
free(databuf.buf);
if (sd != 0)
close(sd);
return NULL;
}
@ -1137,7 +1124,7 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args)
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
if (strcmp(ksp->ks_module, "cpu_info") != 0)
continue;
if (kstat_read(kc, ksp, NULL) == NULL)
if (kstat_read(kc, ksp, NULL) == -1)
goto error;
ncpus += 1;
}
@ -1152,8 +1139,117 @@ error:
// mimic os.cpu_count()
if (kc != NULL)
kstat_close(kc);
Py_INCREF(Py_None);
return Py_None;
Py_RETURN_NONE;
}
/*
* Return stats about a particular network
* interface. References:
* https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py
* http://www.i-scream.org/libstatgrab/
*/
static PyObject*
psutil_net_if_stats(PyObject* self, PyObject* args)
{
kstat_ctl_t *kc = NULL;
kstat_t *ksp;
kstat_named_t *knp;
int ret;
int sock = 0;
int duplex;
int speed;
PyObject *py_retdict = PyDict_New();
PyObject *py_ifc_info = NULL;
PyObject *py_is_up = NULL;
if (py_retdict == NULL)
return NULL;
kc = kstat_open();
if (kc == NULL)
goto error;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1)
goto error;
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
if (strcmp(ksp->ks_class, "net") == 0) {
struct ifreq ifr;
kstat_read(kc, ksp, NULL);
if (ksp->ks_type != KSTAT_TYPE_NAMED)
continue;
if (strcmp(ksp->ks_class, "net") != 0)
continue;
strncpy(ifr.ifr_name, ksp->ks_name, sizeof(ifr.ifr_name));
ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
if (ret == -1)
continue; // not a network interface
// is up?
if ((ifr.ifr_flags & IFF_UP) != 0) {
if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) {
if (knp->value.ui32 != 0u)
py_is_up = Py_True;
else
py_is_up = Py_False;
}
else {
py_is_up = Py_True;
}
}
else {
py_is_up = Py_False;
}
Py_INCREF(py_is_up);
// duplex
duplex = 0; // unknown
if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) {
if (knp->value.ui32 == 1)
duplex = 1; // half
else if (knp->value.ui32 == 2)
duplex = 2; // full
}
// speed
if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL)
// expressed in bits per sec, we want mega bits per sec
speed = (int)knp->value.ui64 / 1000000;
else
speed = 0;
// mtu
ret = ioctl(sock, SIOCGIFMTU, &ifr);
if (ret == -1)
goto error;
py_ifc_info = Py_BuildValue("(Oiii)", py_is_up, duplex, speed,
ifr.ifr_mtu);
if (!py_ifc_info)
goto error;
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info))
goto error;
Py_DECREF(py_ifc_info);
}
}
close(sock);
kstat_close(kc);
return py_retdict;
error:
Py_XDECREF(py_is_up);
Py_XDECREF(py_ifc_info);
Py_DECREF(py_retdict);
if (sock != 0)
close(sock);
if (kc != NULL)
kstat_close(kc);
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
@ -1198,6 +1294,8 @@ PsutilMethods[] =
"Return the number of physical CPUs on the system."},
{"net_connections", psutil_net_connections, METH_VARARGS,
"Return TCP and UDP syste-wide open connections."},
{"net_if_stats", psutil_net_if_stats, METH_VARARGS,
"Return NIC stats (isup, duplex, speed, mtu)"},
{NULL, NULL, 0, NULL}
};
@ -1254,6 +1352,8 @@ void init_psutil_sunos(void)
#else
PyObject *module = Py_InitModule("_psutil_sunos", PsutilMethods);
#endif
PyModule_AddIntConstant(module, "version", PSUTIL_VERSION);
PyModule_AddIntConstant(module, "SSLEEP", SSLEEP);
PyModule_AddIntConstant(module, "SRUN", SRUN);
PyModule_AddIntConstant(module, "SZOMB", SZOMB);
@ -1281,9 +1381,8 @@ void init_psutil_sunos(void)
PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND);
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
if (module == NULL) {
if (module == NULL)
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
#endif

View File

@ -25,3 +25,4 @@ static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_net_connections(PyObject* self, PyObject* args);
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);

File diff suppressed because it is too large Load Diff

View File

@ -13,22 +13,18 @@ static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times_2(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time_2(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
static PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
static PyObject* psutil_proc_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_counters_2(PyObject* self, PyObject* args);
static PyObject* psutil_proc_is_suspended(PyObject* self, PyObject* args);
static PyObject* psutil_proc_kill(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info_2(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_handles(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_handles_2(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
static PyObject* psutil_proc_priority_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_priority_set(PyObject* self, PyObject* args);
@ -60,6 +56,8 @@ static PyObject* psutil_pids(PyObject* self, PyObject* args);
static PyObject* psutil_ppid_map(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args);
static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args);
// --- windows API bindings

View File

@ -7,21 +7,35 @@
"""Windows platform implementation."""
import errno
import functools
import os
import sys
from collections import namedtuple
from psutil import _common
from psutil._common import conn_tmap, usage_percent, isfile_strict
from psutil._compat import PY3, xrange, wraps, lru_cache, namedtuple
import _psutil_windows as cext
from . import _common
from . import _psutil_windows as cext
from ._common import conn_tmap, usage_percent, isfile_strict
from ._common import sockfam_to_enum, socktype_to_enum
from ._compat import PY3, xrange, lru_cache, long
from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
REALTIME_PRIORITY_CLASS)
if sys.version_info >= (3, 4):
import enum
else:
enum = None
# process priority constants, import from __init__.py:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
__extra__all__ = ["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",
]
# --- module level constants (gets pushed up to psutil module)
@ -30,6 +44,11 @@ CONN_DELETE_TCB = "DELETE_TCB"
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES,
cext.ERROR_ACCESS_DENIED])
if enum is None:
AF_LINK = -1
else:
AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1})
AF_LINK = AddressFamily.AF_LINK
TCP_STATUSES = {
cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED,
@ -47,6 +66,16 @@ TCP_STATUSES = {
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
if enum is not None:
class Priority(enum.IntEnum):
ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS
BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS
HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS
IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS
NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS
REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS
globals().update(Priority.__members__)
scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
@ -57,6 +86,10 @@ pextmem = namedtuple(
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
ntpinfo = namedtuple(
'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time',
'create_time', 'num_threads', 'io_rcount', 'io_wcount',
'io_rbytes', 'io_wbytes'])
# set later from __init__.py
NoSuchProcess = None
@ -166,15 +199,27 @@ def net_connections(kind, _pid=-1):
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = cext.net_connections(_pid, families, types)
ret = []
ret = set()
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
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)
ret.append(nt)
ret.add(nt)
return list(ret)
def net_if_stats():
ret = cext.net_if_stats()
for name, items in ret.items():
isup, duplex, speed, mtu = items
if hasattr(_common, 'NicDuplex'):
duplex = _common.NicDuplex(duplex)
ret[name] = _common.snicstats(isup, duplex, speed, mtu)
return ret
@ -194,21 +239,21 @@ pid_exists = cext.pid_exists
net_io_counters = cext.net_io_counters
disk_io_counters = cext.disk_io_counters
ppid_map = cext.ppid_map # not meant to be public
net_if_addrs = cext.net_if_addrs
def wrap_exceptions(fun):
"""Decorator which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
@wraps(fun)
@functools.wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
except OSError as err:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
@ -220,11 +265,12 @@ def wrap_exceptions(fun):
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name"]
__slots__ = ["pid", "_name", "_ppid"]
def __init__(self, pid):
self.pid = pid
self._name = None
self._ppid = None
@wrap_exceptions
def name(self):
@ -238,7 +284,12 @@ class Process(object):
elif self.pid == 4:
return "System"
else:
return os.path.basename(self.exe())
try:
# Note: this will fail with AD for most PIDs owned
# by another user but it's faster.
return os.path.basename(self.exe())
except AccessDenied:
return cext.proc_name(self.pid)
@wrap_exceptions
def exe(self):
@ -265,9 +316,10 @@ class Process(object):
def _get_raw_meminfo(self):
try:
return cext.proc_memory_info(self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
# TODO: the C ext can probably be refactored in order
# to get this from cext.proc_info()
return cext.proc_memory_info_2(self.pid)
raise
@ -287,10 +339,9 @@ class Process(object):
def memory_maps(self):
try:
raw = cext.proc_memory_maps(self.pid)
except OSError:
except OSError as err:
# XXX - can't use wrap_exceptions decorator as we're
# returning a generator; probably needs refactoring.
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._name)
if err.errno == errno.ESRCH:
@ -334,15 +385,14 @@ class Process(object):
return boot_time()
try:
return cext.proc_create_time(self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
return cext.proc_create_time_2(self.pid)
return ntpinfo(*cext.proc_info(self.pid)).create_time
raise
@wrap_exceptions
def num_threads(self):
return cext.proc_num_threads(self.pid)
return ntpinfo(*cext.proc_info(self.pid)).num_threads
@wrap_exceptions
def threads(self):
@ -357,10 +407,10 @@ class Process(object):
def cpu_times(self):
try:
ret = cext.proc_cpu_times(self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_cpu_times_2(self.pid)
nt = ntpinfo(*cext.proc_info(self.pid))
ret = (nt.user_time, nt.kernel_time)
else:
raise
return _common.pcputimes(*ret)
@ -392,10 +442,10 @@ class Process(object):
# Convert the first part in the corresponding drive letter
# (e.g. "C:\") by using Windows's QueryDosDevice()
raw_file_names = cext.proc_open_files(self.pid)
for file in raw_file_names:
file = _convert_raw_path(file)
if isfile_strict(file) and file not in retlist:
ntuple = _common.popenfile(file, -1)
for _file in raw_file_names:
_file = _convert_raw_path(_file)
if isfile_strict(_file) and _file not in retlist:
ntuple = _common.popenfile(_file, -1)
retlist.append(ntuple)
return retlist
@ -405,7 +455,10 @@ class Process(object):
@wrap_exceptions
def nice_get(self):
return cext.proc_priority_get(self.pid)
value = cext.proc_priority_get(self.pid)
if enum is not None:
value = Priority(value)
return value
@wrap_exceptions
def nice_set(self, value):
@ -431,10 +484,10 @@ class Process(object):
def io_counters(self):
try:
ret = cext.proc_io_counters(self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_io_counters_2(self.pid)
nt = ntpinfo(*cext.proc_info(self.pid))
ret = (nt.io_rcount, nt.io_wcount, nt.io_rbytes, nt.io_wbytes)
else:
raise
return _common.pio(*ret)
@ -449,7 +502,8 @@ class Process(object):
@wrap_exceptions
def cpu_affinity_get(self):
from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x]
def from_bitmask(x):
return [i for i in xrange(64) if (1 << i) & x]
bitmask = cext.proc_cpu_affinity_get(self.pid)
return from_bitmask(bitmask)
@ -469,7 +523,11 @@ class Process(object):
allcpus = list(range(len(per_cpu_times())))
for cpu in value:
if cpu not in allcpus:
raise ValueError("invalid CPU %r" % cpu)
if not isinstance(cpu, (int, long)):
raise TypeError(
"invalid CPU %r; an integer is required" % cpu)
else:
raise ValueError("invalid CPU %r" % cpu)
bitmask = to_bitmask(value)
cext.proc_cpu_affinity_set(self.pid, bitmask)
@ -478,13 +536,13 @@ class Process(object):
def num_handles(self):
try:
return cext.proc_num_handles(self.pid)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno in ACCESS_DENIED_SET:
return cext.proc_num_handles_2(self.pid)
return ntpinfo(*cext.proc_info(self.pid)).num_handles
raise
@wrap_exceptions
def num_ctx_switches(self):
tupl = cext.proc_num_ctx_switches(self.pid)
return _common.pctxsw(*tupl)
ctx_switches = ntpinfo(*cext.proc_info(self.pid)).ctx_switches
# only voluntary ctx switches are supported
return _common.pctxsw(ctx_switches, 0)

View File

@ -128,9 +128,8 @@ char
mib[3] = pid;
// call with a null buffer first to determine if we need a buffer
if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1) {
if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1)
return NULL;
}
path = malloc(size);
if (path == NULL) {
@ -213,14 +212,11 @@ psutil_get_arg_list(long pid)
PyObject *retlist = Py_BuildValue("[]");
PyObject *item = NULL;
if (pid < 0) {
if (pid < 0)
return retlist;
}
argstr = psutil_get_cmd_args(pid, &argsize);
if (argstr == NULL) {
if (argstr == NULL)
goto error;
}
// args are returned as a flattened string with \0 separators between
// arguments add each string to the list then step forward to the next
@ -256,30 +252,14 @@ int
psutil_pid_exists(long pid)
{
int kill_ret;
if (pid < 0) {
return 0;
}
if (pid < 0)
return 0;
// if kill returns success of permission denied we know it's a valid PID
kill_ret = kill(pid , 0);
if ((0 == kill_ret) || (EPERM == errno)) {
if ((0 == kill_ret) || (EPERM == errno))
return 1;
}
// otherwise return 0 for PID not found
return 0;
}
/*
* Set exception to AccessDenied if pid exists else NoSuchProcess.
*/
int
psutil_raise_ad_or_nsp(pid) {
if (psutil_pid_exists(pid) == 0) {
NoSuchProcess();
}
else {
AccessDenied();
}
}

View File

@ -32,15 +32,12 @@ psutil_pid_exists(long pid)
int kill_ret;
// save some time if it's an invalid PID
if (pid < 0) {
if (pid < 0)
return 0;
}
// if kill returns success of permission denied we know it's a valid PID
kill_ret = kill(pid , 0);
if ( (0 == kill_ret) || (EPERM == errno) ) {
if ( (0 == kill_ret) || (EPERM == errno))
return 1;
}
// otherwise return 0 for PID not found
return 0;
@ -85,34 +82,29 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
*/
while (lim-- > 0) {
size = 0;
if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) {
if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1)
return errno;
}
size2 = size + (size >> 3); // add some
if (size2 > size) {
ptr = malloc(size2);
if (ptr == NULL) {
if (ptr == NULL)
ptr = malloc(size);
} else {
else
size = size2;
}
}
else {
ptr = malloc(size);
}
if (ptr == NULL) {
if (ptr == NULL)
return ENOMEM;
}
if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) {
err = errno;
free(ptr);
if (err != ENOMEM) {
if (err != ENOMEM)
return err;
}
} else {
}
else {
*procList = (kinfo_proc *)ptr;
*procCount = size / sizeof(kinfo_proc);
return 0;
@ -130,9 +122,8 @@ psutil_get_argmax()
int mib[] = { CTL_KERN, KERN_ARGMAX };
size_t size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) {
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0)
return argmax;
}
return 0;
}
@ -153,9 +144,8 @@ psutil_get_arg_list(long pid)
PyObject *arglist = NULL;
// special case for PID 0 (kernel_task) where cmdline cannot be fetched
if (pid == 0) {
if (pid == 0)
return Py_BuildValue("[]");
}
// read argmax and allocate memory for argument space.
argmax = psutil_get_argmax();
@ -177,11 +167,10 @@ psutil_get_arg_list(long pid)
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
if (EINVAL == errno) {
// EINVAL == access denied OR nonexistent PID
if ( psutil_pid_exists(pid) ) {
if (psutil_pid_exists(pid))
AccessDenied();
} else {
else
NoSuchProcess();
}
}
goto error;
}
@ -201,9 +190,8 @@ psutil_get_arg_list(long pid)
// skip ahead to the first argument
for (; arg_ptr < arg_end; arg_ptr++) {
if (*arg_ptr != '\0') {
if (*arg_ptr != '\0')
break;
}
}
// iterate through arguments

View File

@ -0,0 +1,41 @@
#include "inet_ntop.h"
// From: https://memset.wordpress.com/2010/10/09/inet_ntop-for-win32/
PCSTR
WSAAPI
inet_ntop(
__in INT Family,
__in PVOID pAddr,
__out_ecount(StringBufSize) PSTR pStringBuf,
__in size_t StringBufSize
)
{
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 {
return NULL;
}
if (WSAAddressToString((LPSOCKADDR) &srcaddr,
dwAddressLength,
0,
pStringBuf,
(LPDWORD) &StringBufSize) != 0) {
return NULL;
}
return pStringBuf;
}

View File

@ -0,0 +1,10 @@
#include <ws2tcpip.h>
PCSTR
WSAAPI
inet_ntop(
__in INT Family,
__in PVOID pAddr,
__out_ecount(StringBufSize) PSTR pStringBuf,
__in size_t StringBufSize
);

View File

@ -3,6 +3,9 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#if !defined(__NTEXTAPI_H__)
#define __NTEXTAPI_H__
#include <winternl.h>
typedef enum _KTHREAD_STATE {
Initialized,
@ -63,23 +66,6 @@ typedef struct _CLIENT_ID {
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
LARGE_INTEGER BootTime;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER TimeZoneBias;
ULONG TimeZoneId;
ULONG Reserved;
ULONGLONG BootTimeBias;
ULONGLONG SleepTimeBias;
} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
@ -108,7 +94,7 @@ typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
ULONG_PTR Reserved4;
} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION;
typedef struct _SYSTEM_PROCESS_INFORMATION {
typedef struct _SYSTEM_PROCESS_INFORMATION2 {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
@ -143,31 +129,10 @@ typedef struct _SYSTEM_PROCESS_INFORMATION {
LARGE_INTEGER WriteTransferCount;
LARGE_INTEGER OtherTransferCount;
SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
} SYSTEM_PROCESS_INFORMATION2, *PSYSTEM_PROCESS_INFORMATION2;
// structures and enums from winternl.h (not available under mingw)
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;
#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2
#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2
// ================================================
@ -186,32 +151,9 @@ typedef struct _WINSTATION_INFO {
FILETIME CurrentTime;
} WINSTATION_INFO, *PWINSTATION_INFO;
typedef enum _WINSTATIONINFOCLASS {
WinStationInformation = 8
} WINSTATIONINFOCLASS;
typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW)
(HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG);
typedef struct _WINSTATIONINFORMATIONW {
BYTE Reserved2[70];
ULONG LogonId;
BYTE Reserved3[1140];
} WINSTATIONINFORMATIONW, *PWINSTATIONINFORMATIONW;
// mingw support:
// http://www.koders.com/c/fid7C02CAE627C526914CDEB427405B51DF393A5EFA.aspx
#ifndef _INC_WTSAPI
typedef struct _WTS_CLIENT_ADDRESS {
DWORD AddressFamily; // AF_INET, AF_IPX, AF_NETBIOS, AF_UNSPEC
BYTE Address[20]; // client network address
} WTS_CLIENT_ADDRESS, * PWTS_CLIENT_ADDRESS;
HANDLE WINAPI WTSOpenServerA(IN LPSTR pServerName);
VOID WINAPI WTSCloseServer(IN HANDLE hServer);
#endif
/*
* NtQueryInformationProcess code taken from
@ -235,16 +177,9 @@ typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
DWORD ProcessInformationLength
);
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PVOID PebBaseAddress;
PVOID Reserved2[2];
ULONG_PTR UniqueProcessId;
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation,
typedef enum _PROCESSINFOCLASS2 {
_ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
@ -270,7 +205,7 @@ typedef enum _PROCESSINFOCLASS {
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
_ProcessWow64Information,
/* added after XP+ */
ProcessImageFileName,
ProcessLUIDDeviceMapsEnabled,
@ -284,4 +219,10 @@ typedef enum _PROCESSINFOCLASS {
ProcessCookie,
ProcessImageInformation,
MaxProcessInfoClass
} PROCESSINFOCLASS;
} PROCESSINFOCLASS2;
#define PROCESSINFOCLASS PROCESSINFOCLASS2
#define ProcessBasicInformation _ProcessBasicInformation
#define ProcessWow64Information _ProcessWow64Information
#endif // __NTEXTAPI_H__

View File

@ -4,108 +4,22 @@
* found in the LICENSE file.
*
*/
#ifndef UNICODE
#define UNICODE
#endif
#include <Python.h>
#include <windows.h>
#include <stdio.h>
#include "process_handles.h"
#ifndef NT_SUCCESS
#define NT_SUCCESS(x) ((x) >= 0)
#endif
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
static _NtQuerySystemInformation __NtQuerySystemInformation = NULL;
static _NtQueryObject __NtQueryObject = NULL;
#define SystemHandleInformation 16
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
typedef LONG NTSTATUS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
HANDLE SourceProcessHandle,
HANDLE SourceHandle,
HANDLE TargetProcessHandle,
PHANDLE TargetHandle,
ACCESS_MASK DesiredAccess,
ULONG Attributes,
ULONG Options
);
typedef NTSTATUS (NTAPI *_NtQueryObject)(
HANDLE ObjectHandle,
ULONG ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
);
typedef struct _SYSTEM_HANDLE {
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef enum _POOL_TYPE {
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
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;
PVOID g_fiber = NULL;
PVOID
@ -114,224 +28,506 @@ GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
}
PyObject *
psutil_get_open_files(long dwPid, HANDLE hProcess)
{
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
// Threaded version only works for Vista+
if (osvi.dwMajorVersion >= 6)
return psutil_get_open_files_ntqueryobject(dwPid, hProcess);
else
return psutil_get_open_files_getmappedfilename(dwPid, hProcess);
}
VOID
psutil_get_open_files_init(BOOL threaded)
{
if (g_initialized == TRUE)
return;
// Resolve the Windows API calls
__NtQuerySystemInformation =
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
__NtQueryObject = GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
// 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);
}
g_initialized = TRUE;
}
PyObject *
psutil_get_open_files(long pid, HANDLE processHandle)
psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess)
{
_NtQuerySystemInformation NtQuerySystemInformation =
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
_NtQueryObject NtQueryObject =
GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
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;
PyObject* pyListFiles = NULL;
PyObject* pyFilePath = NULL;
DWORD dwWait = 0;
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG i;
ULONG fileNameLength;
PyObject *filesList = Py_BuildValue("[]");
PyObject *arg = NULL;
PyObject *fileFromWchar = NULL;
if (g_initialized == FALSE)
psutil_get_open_files_init(TRUE);
if (filesList == NULL)
return NULL;
// Due to the use of global variables, ensure only 1 call
// to psutil_get_open_files() is running
EnterCriticalSection(&g_cs);
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
if (handleInfo == NULL) {
Py_DECREF(filesList);
PyErr_NoMemory();
return NULL;
}
if (__NtQuerySystemInformation == NULL ||
__NtQueryObject == NULL ||
g_hEvtStart == NULL ||
g_hEvtFinish == NULL)
// NtQuerySystemInformation won't give us the correct buffer size,
// so we guess by doubling the buffer size.
while ((status = NtQuerySystemInformation(
SystemHandleInformation,
handleInfo,
handleInfoSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
handleInfo = (PSYSTEM_HANDLE_INFORMATION) \
realloc(handleInfo, handleInfoSize *= 2);
PyErr_SetFromWindowsErr(0);
error = TRUE;
goto cleanup;
}
// Py_BuildValue raises an exception if NULL is returned
pyListFiles = PyList_New(0);
if (pyListFiles == 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 = __NtQuerySystemInformation(
SystemExtendedHandleInformation,
pHandleInfo,
dwInfoSize,
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
if (!NT_SUCCESS(status)) {
Py_DECREF(filesList);
free(handleInfo);
return NULL;
PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status));
error = TRUE;
goto cleanup;
}
for (i = 0; i < handleInfo->HandleCount; i++) {
SYSTEM_HANDLE handle = handleInfo->Handles[i];
HANDLE dupHandle = NULL;
HANDLE mapHandle = NULL;
POBJECT_TYPE_INFORMATION objectTypeInfo = NULL;
PVOID objectNameInfo;
UNICODE_STRING objectName;
ULONG returnLength;
DWORD error = 0;
fileFromWchar = NULL;
arg = NULL;
for (i = 0; i < pHandleInfo->NumberOfHandles; i++) {
hHandle = &pHandleInfo->Handles[i];
// Check if this handle belongs to the PID the user specified.
if (handle.ProcessId != pid)
continue;
// Check if this hHandle belongs to the PID the user specified.
if (hHandle->UniqueProcessId != (HANDLE)dwPid ||
hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE)
goto loop_cleanup;
// Skip handles with the following access codes as the next call
// to NtDuplicateObject() or NtQueryObject() might hang forever.
if ((handle.GrantedAccess == 0x0012019f)
|| (handle.GrantedAccess == 0x001a019f)
|| (handle.GrantedAccess == 0x00120189)
|| (handle.GrantedAccess == 0x00100000)) {
continue;
}
if (!DuplicateHandle(processHandle,
handle.Handle,
if (!DuplicateHandle(hProcess,
hHandle->HandleValue,
GetCurrentProcess(),
&dupHandle,
&g_hFile,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
{
//printf("[%#x] Error: %d \n", handle.Handle, GetLastError());
continue;
}
{
/*
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);
mapHandle = CreateFileMapping(dupHandle,
NULL,
PAGE_READONLY,
0,
0,
NULL);
if (mapHandle == NULL) {
error = GetLastError();
if (error == ERROR_INVALID_HANDLE || error == ERROR_BAD_EXE_FORMAT) {
CloseHandle(dupHandle);
//printf("CreateFileMapping Error: %d\n", error);
continue;
do {
// Release any previously allocated buffer
if (g_pNameBuffer != NULL) {
HeapFree(GetProcessHeap(), 0, g_pNameBuffer);
g_pNameBuffer = NULL;
g_dwSize = 0;
}
}
CloseHandle(mapHandle);
// Query the object type.
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectTypeInformation,
objectTypeInfo,
0x1000,
NULL
)))
{
free(objectTypeInfo);
CloseHandle(dupHandle);
continue;
}
// 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;
objectNameInfo = malloc(0x1000);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
0x1000,
&returnLength
)))
{
// Reallocate the buffer and try again.
objectNameInfo = realloc(objectNameInfo, returnLength);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
returnLength,
NULL
)))
{
// We have the type name, so just display that.
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_NtQueryObject();
// 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);
*/
pyFilePath = PyUnicode_FromWideChar(g_pNameBuffer->Buffer,
g_pNameBuffer->Length/2);
if (pyFilePath == NULL) {
/*
printf(
"[%#x] %.*S: (could not get name)\n",
handle.Handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer
);
printf("[%d] PyUnicode_FromWideChar (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
free(objectTypeInfo);
free(objectNameInfo);
CloseHandle(dupHandle);
continue;
error = TRUE;
goto loop_cleanup;
}
if (PyList_Append(pyListFiles, pyFilePath)) {
/*
printf("[%d] PyList_Append (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
}
// Cast our buffer into an UNICODE_STRING.
objectName = *(PUNICODE_STRING)objectNameInfo;
loop_cleanup:
Py_XDECREF(pyFilePath);
pyFilePath = NULL;
// Print the information!
if (objectName.Length)
{
// The object has a name. Make sure it is a file otherwise
// ignore it
fileNameLength = objectName.Length / 2;
if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) {
// printf("%.*S\n", objectName.Length / 2, objectName.Buffer);
fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer,
fileNameLength);
if (fileFromWchar == NULL)
goto error_py_fun;
#if PY_MAJOR_VERSION >= 3
arg = Py_BuildValue("N",
PyUnicode_AsUTF8String(fileFromWchar));
#else
arg = Py_BuildValue("N",
PyUnicode_FromObject(fileFromWchar));
#endif
if (!arg)
goto error_py_fun;
Py_XDECREF(fileFromWchar);
fileFromWchar = NULL;
if (PyList_Append(filesList, arg))
goto error_py_fun;
Py_XDECREF(arg);
}
/*
printf(
"[%#x] %.*S: %.*S\n",
handle.Handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer,
objectName.Length / 2,
objectName.Buffer
);
*/
}
else
{
// Print something else.
/*
printf(
"[%#x] %.*S: (unnamed)\n",
handle.Handle,
objectTypeInfo->Name.Length / 2,
objectTypeInfo->Name.Buffer
);
*/
;;
}
free(objectTypeInfo);
free(objectNameInfo);
CloseHandle(dupHandle);
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;
}
free(handleInfo);
CloseHandle(processHandle);
return filesList;
error_py_fun:
Py_XDECREF(arg);
Py_XDECREF(fileFromWchar);
Py_DECREF(filesList);
return 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(pyListFiles);
pyListFiles = NULL;
}
LeaveCriticalSection(&g_cs);
return pyListFiles;
}
DWORD
psutil_NtQueryObject()
{
DWORD dwWait = 0;
if (g_hThread == NULL)
g_hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)psutil_NtQueryObjectThread,
NULL,
0,
NULL);
if (g_hThread == NULL)
return GetLastError();
// Signal the worker thread to start
SetEvent(g_hEvtStart);
// Wait for the worker thread to finish
dwWait = WaitForSingleObject(g_hEvtFinish, NTQO_TIMEOUT);
// 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);
// Cleanup Fiber
if (g_fiber != NULL)
DeleteFiber(g_fiber);
g_fiber = NULL;
g_hThread = NULL;
}
return dwWait;
}
void
psutil_NtQueryObjectThread()
{
// Prevent the thread stack from leaking when this
// thread gets terminated due to NTQueryObject hanging
g_fiber = ConvertThreadToFiber(NULL);
// Loop infinitely waiting for work
while (TRUE) {
WaitForSingleObject(g_hEvtStart, INFINITE);
g_status = __NtQueryObject(g_hFile,
ObjectNameInformation,
g_pNameBuffer,
g_dwSize,
&g_dwLength);
SetEvent(g_hEvtFinish);
}
}
PyObject *
psutil_get_open_files_getmappedfilename(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;
HANDLE hFile = NULL;
HANDLE hMap = NULL;
DWORD i = 0;
BOOLEAN error = FALSE;
PyObject* pyListFiles = NULL;
PyObject* pyFilePath = NULL;
ULONG dwSize = 0;
LPVOID pMem = NULL;
TCHAR pszFilename[MAX_PATH+1];
if (g_initialized == FALSE)
psutil_get_open_files_init(FALSE);
if (__NtQuerySystemInformation == NULL || __NtQueryObject == NULL) {
PyErr_SetFromWindowsErr(0);
error = TRUE;
goto cleanup;
}
// Py_BuildValue raises an exception if NULL is returned
pyListFiles = PyList_New(0);
if (pyListFiles == 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 = __NtQuerySystemInformation(
SystemExtendedHandleInformation,
pHandleInfo,
dwInfoSize,
&dwRet)) == STATUS_INFO_LENGTH_MISMATCH);
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
if (!NT_SUCCESS(status)) {
PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status));
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 != (HANDLE)dwPid ||
hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE)
goto loop_cleanup;
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;
}
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;
}
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;
}
dwSize = GetMappedFileName(GetCurrentProcess(), pMem, 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);
*/
pyFilePath = PyUnicode_FromWideChar(pszFilename, dwSize);
if (pyFilePath == NULL) {
/*
printf("[%d] PyUnicode_FromStringAndSize (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
if (PyList_Append(pyListFiles, pyFilePath)) {
/*
printf("[%d] PyList_Append (%#x): %#x \n",
dwPid,
hHandle->HandleValue,
GetLastError());
*/
error = TRUE;
goto loop_cleanup;
}
loop_cleanup:
Py_XDECREF(pyFilePath);
pyFilePath = NULL;
if (pMem != NULL)
UnmapViewOfFile(pMem);
pMem = NULL;
if (hMap != NULL)
CloseHandle(hMap);
hMap = NULL;
if (hFile != NULL)
CloseHandle(hFile);
hFile = NULL;
dwSize = 0;
}
cleanup:
if (pMem != NULL)
UnmapViewOfFile(pMem);
pMem = NULL;
if (hMap != NULL)
CloseHandle(hMap);
hMap = NULL;
if (hFile != NULL)
CloseHandle(hFile);
hFile = NULL;
if (pHandleInfo != NULL)
HeapFree(GetProcessHeap(), 0, pHandleInfo);
pHandleInfo = NULL;
if (error) {
Py_XDECREF(pyListFiles);
pyListFiles = NULL;
}
return pyListFiles;
}

View File

@ -4,7 +4,110 @@
* found in the LICENSE file.
*/
#include <Python.h>
#include <windows.h>
#ifndef __PROCESS_HANDLES_H__
#define __PROCESS_HANDLES_H__
#ifndef UNICODE
#define UNICODE
#endif
#include <Python.h>
#include <stdio.h>
#include <windows.h>
#include <strsafe.h>
#include <winternl.h>
#include <psapi.h>
#ifndef NT_SUCCESS
#define NT_SUCCESS(x) ((x) >= 0)
#endif
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
#define ObjectBasicInformation 0
#define ObjectNameInformation 1
#define ObjectTypeInformation 2
#define HANDLE_TYPE_FILE 28
#define NTQO_TIMEOUT 100
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef NTSTATUS (NTAPI *_NtQueryObject)(
HANDLE ObjectHandle,
ULONG ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
);
// Undocumented FILE_INFORMATION_CLASS: FileNameInformation
static const SYSTEM_INFORMATION_CLASS SystemExtendedHandleInformation = (SYSTEM_INFORMATION_CLASS)64;
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
PVOID Object;
HANDLE UniqueProcessId;
HANDLE HandleValue;
ULONG GrantedAccess;
USHORT CreatorBackTraceIndex;
USHORT ObjectTypeIndex;
ULONG HandleAttributes;
ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;
typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
ULONG_PTR NumberOfHandles;
ULONG_PTR Reserved;
SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
typedef enum _POOL_TYPE {
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName);
VOID psutil_get_open_files_init(BOOL threaded);
PyObject* psutil_get_open_files(long pid, HANDLE processHandle);
PyObject* psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess);
PyObject* psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess);
DWORD psutil_NtQueryObject(void);
void psutil_NtQueryObjectThread(void);
#endif // __PROCESS_HANDLES_H__

View File

@ -38,12 +38,10 @@ psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
hProcess = OpenProcess(dwDesiredAccess, FALSE, pid);
if (hProcess == NULL) {
if (GetLastError() == ERROR_INVALID_PARAMETER) {
if (GetLastError() == ERROR_INVALID_PARAMETER)
NoSuchProcess();
}
else {
else
PyErr_SetFromWindowsErr(0);
}
return NULL;
}
@ -129,13 +127,10 @@ psutil_pid_is_running(DWORD pid)
DWORD exitCode;
// Special case for PID 0 System Idle Process
if (pid == 0) {
if (pid == 0)
return 1;
}
if (pid < 0) {
if (pid < 0)
return 0;
}
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
@ -183,10 +178,8 @@ psutil_pid_in_proclist(DWORD pid)
DWORD i;
proclist = psutil_get_pids(&numberOfReturnedPIDs);
if (NULL == proclist) {
if (proclist == NULL)
return -1;
}
for (i = 0; i < numberOfReturnedPIDs; i++) {
if (pid == proclist[i]) {
free(proclist);
@ -205,13 +198,12 @@ int
handlep_is_running(HANDLE hProcess)
{
DWORD dwCode;
if (NULL == hProcess) {
if (NULL == hProcess)
return 0;
}
if (GetExitCodeProcess(hProcess, &dwCode)) {
if (dwCode == STILL_ACTIVE) {
if (dwCode == STILL_ACTIVE)
return 1;
}
}
return 0;
}
@ -236,10 +228,8 @@ psutil_get_arg_list(long pid)
PyObject *argList = NULL;
hProcess = psutil_handle_from_pid(pid);
if (hProcess == NULL) {
if (hProcess == NULL)
return NULL;
}
pebAddress = psutil_get_peb_address(hProcess);
// get the address of ProcessParameters
@ -367,7 +357,10 @@ const int STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
/*
* Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
* fills the structure with process information.
* fills the structure with 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.
* On success return 1, else 0 with Python exception already set.
*/
int
@ -419,9 +412,8 @@ psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
goto error;
}
if (bufferSize <= 0x20000) {
if (bufferSize <= 0x20000)
initialBufferSize = bufferSize;
}
process = PH_FIRST_PROCESS(buffer);
do {

View File

@ -4,8 +4,13 @@
* found in the LICENSE file.
*/
#if !defined(__PROCESS_INFO_H)
#define __PROCESS_INFO_H
#include <Python.h>
#include <windows.h>
#include "security.h"
#include "ntextapi.h"
DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
HANDLE psutil_handle_from_pid(DWORD pid);
@ -15,3 +20,7 @@ int psutil_pid_in_proclist(DWORD pid);
int psutil_pid_is_running(DWORD pid);
PVOID psutil_get_peb_address(HANDLE ProcessHandle);
PyObject* psutil_get_arg_list(long pid);
int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
PVOID *retBuffer);
#endif

View File

@ -18,9 +18,8 @@ HANDLE
psutil_token_from_handle(HANDLE hProcess) {
HANDLE hToken = NULL;
if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
return PyErr_SetFromWindowsErr(0);
}
return hToken;
}
@ -50,10 +49,8 @@ psutil_has_system_privilege(HANDLE hProcess) {
TOKEN_PRIVILEGES *tp = NULL;
HANDLE hToken = psutil_token_from_handle(hProcess);
if (NULL == hToken) {
if (NULL == hToken)
return -1;
}
// call GetTokenInformation first to get the buffer size
if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) {
dwRetval = GetLastError();
@ -140,14 +137,11 @@ psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege)
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if (bEnablePrivilege) {
if (bEnablePrivilege)
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
}
else {
else
tpPrevious.Privileges[0].Attributes ^=
(SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
hToken,
@ -213,15 +207,12 @@ psutil_unset_se_debug()
&hToken)
) {
if (GetLastError() == ERROR_NO_TOKEN) {
if (! ImpersonateSelf(SecurityImpersonation)) {
if (! ImpersonateSelf(SecurityImpersonation))
return 0;
}
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
)
&hToken))
{
return 0;
}
@ -229,9 +220,8 @@ psutil_unset_se_debug()
}
// now disable SeDebug
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) {
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE))
return 0;
}
CloseHandle(hToken);
return 1;

View File

@ -22,8 +22,7 @@ HERE = os.path.abspath(os.path.dirname(__file__))
def get_version():
INIT = os.path.join(HERE, 'psutil/__init__.py')
f = open(INIT, 'r')
try:
with open(INIT, 'r') as f:
for line in f:
if line.startswith('__version__'):
ret = eval(line.strip().split(' = ')[1])
@ -33,24 +32,28 @@ def get_version():
return ret
else:
raise ValueError("couldn't find version string")
finally:
f.close()
def get_description():
README = os.path.join(HERE, 'README.rst')
f = open(README, 'r')
try:
with open(README, 'r') as f:
return f.read()
finally:
f.close()
VERSION = get_version()
VERSION_MACRO = ('PSUTIL_VERSION', int(VERSION.replace('.', '')))
# POSIX
if os.name == 'posix':
libraries = []
if sys.platform.startswith("sunos"):
libraries.append('socket')
posix_extension = Extension(
'_psutil_posix',
'psutil._psutil_posix',
sources=['psutil/_psutil_posix.c'],
libraries=libraries,
)
# Windows
if sys.platform.startswith("win32"):
@ -60,25 +63,28 @@ if sys.platform.startswith("win32"):
return '0x0%s' % ((maj * 100) + min)
extensions = [Extension(
'_psutil_windows',
'psutil._psutil_windows',
sources=[
'psutil/_psutil_windows.c',
'psutil/_psutil_common.c',
'psutil/arch/windows/process_info.c',
'psutil/arch/windows/process_handles.c',
'psutil/arch/windows/security.c',
'psutil/arch/windows/inet_ntop.c',
],
define_macros=[
VERSION_MACRO,
# be nice to mingw, see:
# http://www.mingw.org/wiki/Use_more_recent_defined_functions
('_WIN32_WINNT', get_winver()),
('_AVAIL_WINVER_', get_winver()),
('_CRT_SECURE_NO_WARNINGS', None),
# see: https://github.com/giampaolo/psutil/issues/348
('PSAPI_VERSION', 1),
],
libraries=[
"psapi", "kernel32", "advapi32", "shell32", "netapi32", "iphlpapi",
"wtsapi32",
"wtsapi32", "ws2_32",
],
# extra_compile_args=["/Z7"],
# extra_link_args=["/DEBUG"]
@ -86,12 +92,13 @@ if sys.platform.startswith("win32"):
# OS X
elif sys.platform.startswith("darwin"):
extensions = [Extension(
'_psutil_osx',
'psutil._psutil_osx',
sources=[
'psutil/_psutil_osx.c',
'psutil/_psutil_common.c',
'psutil/arch/osx/process_info.c'
],
define_macros=[VERSION_MACRO],
extra_link_args=[
'-framework', 'CoreFoundation', '-framework', 'IOKit'
],
@ -101,28 +108,31 @@ elif sys.platform.startswith("darwin"):
# FreeBSD
elif sys.platform.startswith("freebsd"):
extensions = [Extension(
'_psutil_bsd',
'psutil._psutil_bsd',
sources=[
'psutil/_psutil_bsd.c',
'psutil/_psutil_common.c',
'psutil/arch/bsd/process_info.c'
],
define_macros=[VERSION_MACRO],
libraries=["devstat"]),
posix_extension,
]
# Linux
elif sys.platform.startswith("linux"):
extensions = [Extension(
'_psutil_linux',
sources=['psutil/_psutil_linux.c']),
'psutil._psutil_linux',
sources=['psutil/_psutil_linux.c'],
define_macros=[VERSION_MACRO]),
posix_extension,
]
# Solaris
elif sys.platform.lower().startswith('sunos'):
extensions = [Extension(
'_psutil_sunos',
'psutil._psutil_sunos',
sources=['psutil/_psutil_sunos.c'],
libraries=['kstat', 'nsl'],),
define_macros=[VERSION_MACRO],
libraries=['kstat', 'nsl', 'socket']),
posix_extension,
]
else:
@ -132,14 +142,14 @@ else:
def main():
setup_args = dict(
name='psutil',
version=get_version(),
version=VERSION,
description=__doc__.replace('\n', '').strip(),
long_description=get_description(),
keywords=[
'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice',
'tty', 'ionice', 'uptime', 'taskmgr', 'process', 'df',
'iotop', 'iostat', 'ifconfig', 'taskset', 'who', 'pidof',
'pmap', 'smem', 'monitoring', 'ulimit', 'prlimit',
'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',
],
author='Giampaolo Rodola',
author_email='g.rodola <at> gmail <dot> com',
@ -166,8 +176,6 @@ def main():
'Operating System :: POSIX',
'Programming Language :: C',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.4',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',

View File

@ -1,15 +0,0 @@
- The recommended way to run tests (also on Windows) is to cd into parent
directory and run:
make test
- If you're on Python < 2.7 unittest2 module must be installed first:
https://pypi.python.org/pypi/unittest2
- The main test script is test_psutil.py, which also imports platform-specific
_*.py scripts (which should be ignored).
- test_memory_leaks.py looks for memory leaks into C extension modules and must
be run separately with:
make memtest

View File

@ -0,0 +1,21 @@
- The recommended way to run tests (also on Windows) is to cd into parent
directory and run ``make test``
- Dependencies for running tests:
- python 2.6: ipaddress, mock, unittest2
- python 2.7: ipaddress, mock
- python 3.2: ipaddress, mock
- python 3.3: ipaddress
- python >= 3.4: no deps required
- The main test script is ``test_psutil.py``, which also imports platform-specific
``_*.py`` scripts (which should be ignored).
- ``test_memory_leaks.py`` looks for memory leaks into C extension modules and must
be run separately with ``make test-memleaks``.
- To run tests on all supported Python version install tox (pip install tox)
then run ``tox``.
- Every time a commit is pushed tests are automatically run on Travis:
https://travis-ci.org/giampaolo/psutil/

View File

@ -8,15 +8,15 @@
"""BSD specific tests. These are implicitly run by test_psutil.py."""
import subprocess
import time
import sys
import os
import subprocess
import sys
import time
import psutil
from psutil._compat import PY3
from test_psutil import (TOLERANCE, sh, get_test_subprocess, which,
from test_psutil import (TOLERANCE, BSD, sh, get_test_subprocess, which,
retry_before_failing, reap_children, unittest)
@ -50,6 +50,7 @@ def muse(field):
return int(line.split()[1])
@unittest.skipUnless(BSD, "not a BSD system")
class BSDSpecificTestCase(unittest.TestCase):
@classmethod
@ -106,6 +107,7 @@ class BSDSpecificTestCase(unittest.TestCase):
if abs(usage.used - used) > 10 * 1024 * 1024:
self.fail("psutil=%s, df=%s" % (usage.used, used))
@retry_before_failing()
def test_memory_maps(self):
out = sh('procstat -v %s' % self.pid)
maps = psutil.Process(self.pid).memory_maps(grouped=False)
@ -120,6 +122,29 @@ class BSDSpecificTestCase(unittest.TestCase):
if not map.path.startswith('['):
self.assertEqual(fields[10], map.path)
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_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_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)
uids = p.uids()
gids = p.gids()
self.assertEqual(uids.real, int(ruid))
self.assertEqual(uids.effective, int(euid))
self.assertEqual(uids.saved, int(suid))
self.assertEqual(gids.real, int(rgid))
self.assertEqual(gids.effective, int(egid))
self.assertEqual(gids.saved, int(sgid))
# --- virtual_memory(); tests against sysctl
def test_vmem_total(self):
@ -162,6 +187,10 @@ class BSDSpecificTestCase(unittest.TestCase):
self.assertAlmostEqual(psutil.virtual_memory().buffers, syst,
delta=TOLERANCE)
def test_cpu_count_logical(self):
syst = sysctl("hw.ncpu")
self.assertEqual(psutil.cpu_count(logical=True), syst)
# --- virtual_memory(); tests against muse
@unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available")
@ -212,12 +241,12 @@ class BSDSpecificTestCase(unittest.TestCase):
delta=TOLERANCE)
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(BSDSpecificTestCase))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -7,18 +7,70 @@
"""Linux specific tests. These are implicitly run by test_psutil.py."""
from __future__ import division
import contextlib
import errno
import fcntl
import io
import os
import pprint
import re
import socket
import struct
import sys
import tempfile
import time
import warnings
from test_psutil import POSIX, TOLERANCE, TRAVIS
try:
from unittest import mock # py3
except ImportError:
import mock # requires "pip install mock"
from test_psutil import POSIX, TOLERANCE, TRAVIS, LINUX
from test_psutil import (skip_on_not_implemented, sh, get_test_subprocess,
retry_before_failing, get_kernel_version, unittest)
retry_before_failing, get_kernel_version, unittest,
which, call_until)
import psutil
import psutil._pslinux
from psutil._compat import PY3, u
SIOCGIFADDR = 0x8915
SIOCGIFCONF = 0x8912
SIOCGIFHWADDR = 0x8927
def get_ipv4_address(ifname):
ifname = ifname[:15]
if PY3:
ifname = bytes(ifname, 'ascii')
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
with contextlib.closing(s):
return socket.inet_ntoa(
fcntl.ioctl(s.fileno(),
SIOCGIFADDR,
struct.pack('256s', ifname))[20:24])
def get_mac_address(ifname):
ifname = ifname[:15]
if PY3:
ifname = bytes(ifname, 'ascii')
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
with contextlib.closing(s):
info = fcntl.ioctl(
s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname))
if PY3:
def ord(x):
return x
else:
import __builtin__
ord = __builtin__.ord
return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1]
@unittest.skipUnless(LINUX, "not a Linux system")
class LinuxSpecificTestCase(unittest.TestCase):
@unittest.skipIf(
@ -139,6 +191,241 @@ class LinuxSpecificTestCase(unittest.TestCase):
else:
self.assertNotIn('guest_nice', fields)
def test_net_if_addrs_ips(self):
for name, addrs in psutil.net_if_addrs().items():
for addr in addrs:
if addr.family == psutil.AF_LINK:
self.assertEqual(addr.address, get_mac_address(name))
elif addr.family == socket.AF_INET:
self.assertEqual(addr.address, get_ipv4_address(name))
# TODO: test for AF_INET6 family
@unittest.skipUnless(which('ip'), "'ip' utility not available")
@unittest.skipIf(TRAVIS, "skipped on Travis")
def test_net_if_names(self):
out = sh("ip addr").strip()
nics = psutil.net_if_addrs()
found = 0
for line in out.split('\n'):
line = line.strip()
if re.search("^\d+:", line):
found += 1
name = line.split(':')[1].strip()
self.assertIn(name, nics.keys())
self.assertEqual(len(nics), found, msg="%s\n---\n%s" % (
pprint.pformat(nics), out))
@unittest.skipUnless(which("nproc"), "nproc utility not available")
def test_cpu_count_logical_w_nproc(self):
num = int(sh("nproc --all"))
self.assertEqual(psutil.cpu_count(logical=True), num)
@unittest.skipUnless(which("lscpu"), "lscpu utility not available")
def test_cpu_count_logical_w_lscpu(self):
out = sh("lscpu -p")
num = len([x for x in out.split('\n') if not x.startswith('#')])
self.assertEqual(psutil.cpu_count(logical=True), num)
# --- mocked tests
def test_virtual_memory_mocked_warnings(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter("always")
ret = psutil._pslinux.virtual_memory()
assert m.called
self.assertEqual(len(ws), 1)
w = ws[0]
self.assertTrue(w.filename.endswith('psutil/_pslinux.py'))
self.assertIn(
"'cached', 'active' and 'inactive' memory stats couldn't "
"be determined", str(w.message))
self.assertEqual(ret.cached, 0)
self.assertEqual(ret.active, 0)
self.assertEqual(ret.inactive, 0)
def test_swap_memory_mocked_warnings(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
with warnings.catch_warnings(record=True) as ws:
warnings.simplefilter("always")
ret = psutil._pslinux.swap_memory()
assert m.called
self.assertEqual(len(ws), 1)
w = ws[0]
self.assertTrue(w.filename.endswith('psutil/_pslinux.py'))
self.assertIn(
"'sin' and 'sout' swap memory stats couldn't "
"be determined", str(w.message))
self.assertEqual(ret.sin, 0)
self.assertEqual(ret.sout, 0)
def test_cpu_count_logical_mocked(self):
import psutil._pslinux
original = psutil._pslinux.cpu_count_logical()
# Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in
# order to cause the parsing of /proc/cpuinfo and /proc/stat.
with mock.patch(
'psutil._pslinux.os.sysconf', side_effect=ValueError) as m:
self.assertEqual(psutil._pslinux.cpu_count_logical(), original)
assert m.called
# Let's have open() return emtpy data and make sure None is
# returned ('cause we mimick os.cpu_count()).
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertIsNone(psutil._pslinux.cpu_count_logical())
self.assertEqual(m.call_count, 2)
# /proc/stat should be the last one
self.assertEqual(m.call_args[0][0], '/proc/stat')
# Let's push this a bit further and make sure /proc/cpuinfo
# parsing works as expected.
with open('/proc/cpuinfo', 'rb') as f:
cpuinfo_data = f.read()
fake_file = io.BytesIO(cpuinfo_data)
with mock.patch('psutil._pslinux.open',
return_value=fake_file, create=True) as m:
self.assertEqual(psutil._pslinux.cpu_count_logical(), original)
def test_cpu_count_physical_mocked(self):
# Have open() return emtpy data and make sure None is returned
# ('cause we want to mimick os.cpu_count())
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertIsNone(psutil._pslinux.cpu_count_physical())
assert m.called
def test_proc_open_files_file_gone(self):
# simulates a file which gets deleted during open_files()
# execution
p = psutil.Process()
files = p.open_files()
with tempfile.NamedTemporaryFile():
# give the kernel some time to see the new file
call_until(p.open_files, "len(ret) != %i" % len(files))
with mock.patch('psutil._pslinux.os.readlink',
side_effect=OSError(errno.ENOENT, "")) as m:
files = p.open_files()
assert not files
assert m.called
# also simulate the case where os.readlink() returns EINVAL
# in which case psutil is supposed to 'continue'
with mock.patch('psutil._pslinux.os.readlink',
side_effect=OSError(errno.EINVAL, "")) as m:
self.assertEqual(p.open_files(), [])
assert m.called
def test_proc_terminal_mocked(self):
with mock.patch('psutil._pslinux._psposix._get_terminal_map',
return_value={}) as m:
self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal())
assert m.called
def test_proc_num_ctx_switches_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).num_ctx_switches)
assert m.called
def test_proc_num_threads_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).num_threads)
assert m.called
def test_proc_ppid_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).ppid)
assert m.called
def test_proc_uids_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).uids)
assert m.called
def test_proc_gids_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).gids)
assert m.called
def test_proc_cmdline_mocked(self):
# see: https://github.com/giampaolo/psutil/issues/639
p = psutil.Process()
fake_file = io.StringIO(u('foo\x00bar\x00'))
with mock.patch('psutil._pslinux.open',
return_value=fake_file, create=True) as m:
p.cmdline() == ['foo', 'bar']
assert m.called
fake_file = io.StringIO(u('foo\x00bar\x00\x00'))
with mock.patch('psutil._pslinux.open',
return_value=fake_file, create=True) as m:
p.cmdline() == ['foo', 'bar', '']
assert m.called
def test_proc_io_counters_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
NotImplementedError,
psutil._pslinux.Process(os.getpid()).io_counters)
assert m.called
def test_boot_time_mocked(self):
with mock.patch('psutil._pslinux.open', create=True) as m:
self.assertRaises(
RuntimeError,
psutil._pslinux.boot_time)
assert m.called
def test_users_mocked(self):
# Make sure ':0' and ':0.0' (returned by C ext) are converted
# to 'localhost'.
with mock.patch('psutil._pslinux.cext.users',
return_value=[('giampaolo', 'pts/2', ':0',
1436573184.0, True)]) as m:
self.assertEqual(psutil.users()[0].host, 'localhost')
assert m.called
with mock.patch('psutil._pslinux.cext.users',
return_value=[('giampaolo', 'pts/2', ':0.0',
1436573184.0, True)]) as m:
self.assertEqual(psutil.users()[0].host, 'localhost')
assert m.called
# ...otherwise it should be returned as-is
with mock.patch('psutil._pslinux.cext.users',
return_value=[('giampaolo', 'pts/2', 'foo',
1436573184.0, True)]) as m:
self.assertEqual(psutil.users()[0].host, 'foo')
assert m.called
def test_disk_partitions_mocked(self):
# Test that ZFS partitions are returned.
with open("/proc/filesystems", "r") as f:
data = f.read()
if 'zfs' in data:
for part in psutil.disk_partitions():
if part.fstype == 'zfs':
break
else:
self.fail("couldn't find any ZFS partition")
else:
# No ZFS partitions on this system. Let's fake one.
fake_file = io.StringIO(u("nodev\tzfs\n"))
with mock.patch('psutil._pslinux.open',
return_value=fake_file, create=True) as m1:
with mock.patch(
'psutil._pslinux.cext.disk_partitions',
return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2:
ret = psutil.disk_partitions()
assert m1.called
assert m2.called
assert ret
self.assertEqual(ret[0].fstype, 'zfs')
# --- tests for specific kernel versions
@unittest.skipUnless(
@ -175,12 +462,12 @@ class LinuxSpecificTestCase(unittest.TestCase):
self.assertTrue(hasattr(psutil, "RLIMIT_SIGPENDING"))
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(LinuxSpecificTestCase))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -15,8 +15,8 @@ import time
import psutil
from psutil._compat import PY3
from test_psutil import (TOLERANCE, sh, get_test_subprocess, reap_children,
retry_before_failing, unittest)
from test_psutil import (TOLERANCE, OSX, sh, get_test_subprocess,
reap_children, retry_before_failing, unittest)
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
@ -47,6 +47,7 @@ def vm_stat(field):
return int(re.search('\d+', line).group(0)) * PAGESIZE
@unittest.skipUnless(OSX, "not an OSX system")
class OSXSpecificTestCase(unittest.TestCase):
@classmethod
@ -148,12 +149,12 @@ class OSXSpecificTestCase(unittest.TestCase):
self.assertEqual(tot1, tot2)
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(OSXSpecificTestCase))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -14,8 +14,8 @@ import time
import psutil
from psutil._compat import PY3
from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON
from psutil._compat import PY3, callable
from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON, POSIX, TRAVIS
from test_psutil import (get_test_subprocess, skip_on_access_denied,
retry_before_failing, reap_children, sh, unittest,
get_kernel_version, wait_for_pid)
@ -42,6 +42,7 @@ def ps(cmd):
return output
@unittest.skipUnless(POSIX, "not a POSIX system")
class PosixSpecificTestCase(unittest.TestCase):
"""Compare psutil results against 'ps' command line utility."""
@ -111,11 +112,14 @@ class PosixSpecificTestCase(unittest.TestCase):
def test_process_create_time(self):
time_ps = ps("ps --no-headers -o start -p %s" % self.pid).split(' ')[0]
time_psutil = psutil.Process(self.pid).create_time()
if SUNOS:
time_psutil = round(time_psutil)
time_psutil_tstamp = datetime.datetime.fromtimestamp(
time_psutil).strftime("%H:%M:%S")
self.assertEqual(time_ps, time_psutil_tstamp)
# sometimes ps shows the time rounded up instead of down, so we check
# for both possible values
round_time_psutil = round(time_psutil)
round_time_psutil_tstamp = datetime.datetime.fromtimestamp(
round_time_psutil).strftime("%H:%M:%S")
self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp])
def test_process_exe(self):
ps_pathname = ps("ps --no-headers -o command -p %s" %
@ -173,9 +177,10 @@ class PosixSpecificTestCase(unittest.TestCase):
[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 differente interfaces
# psutil does
# for some reason ifconfig -a does not report all interfaces
# returned by psutil
@unittest.skipIf(SUNOS, "test not reliable on SUNOS")
@unittest.skipIf(TRAVIS, "test not reliable on Travis")
def test_nic_names(self):
p = subprocess.Popen("ifconfig -a", shell=1, stdout=subprocess.PIPE)
output = p.communicate()[0].strip()
@ -186,7 +191,9 @@ class PosixSpecificTestCase(unittest.TestCase):
if line.startswith(nic):
break
else:
self.fail("couldn't find %s nic in 'ifconfig -a' output" % nic)
self.fail(
"couldn't find %s nic in 'ifconfig -a' output\n%s" % (
nic, output))
@retry_before_failing()
def test_users(self):
@ -208,8 +215,6 @@ class PosixSpecificTestCase(unittest.TestCase):
if attr is not None and callable(attr):
if name == 'rlimit':
args = (psutil.RLIMIT_NOFILE,)
elif name == 'set_rlimit':
args = (psutil.RLIMIT_NOFILE, (5, 5))
attr(*args)
else:
attr
@ -220,11 +225,10 @@ class PosixSpecificTestCase(unittest.TestCase):
'send_signal', 'wait', 'children', 'as_dict']
if LINUX and get_kernel_version() < (2, 6, 36):
ignored_names.append('rlimit')
if LINUX and get_kernel_version() < (2, 6, 23):
ignored_names.append('num_ctx_switches')
for name in dir(psutil.Process):
if (name.startswith('_')
or name.startswith('set_')
or name.startswith('get') # deprecated APIs
or name in ignored_names):
if (name.startswith('_') or name in ignored_names):
continue
else:
try:
@ -243,12 +247,12 @@ class PosixSpecificTestCase(unittest.TestCase):
self.fail('\n' + '\n'.join(failures))
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -7,15 +7,17 @@
"""Sun OS specific tests. These are implicitly run by test_psutil.py."""
import sys
import os
from test_psutil import sh, unittest
from test_psutil import SUNOS, sh, unittest
import psutil
@unittest.skipUnless(SUNOS, "not a SunOS system")
class SunOSSpecificTestCase(unittest.TestCase):
def test_swap_memory(self):
out = sh('swap -l -k')
out = sh('env PATH=/usr/sbin:/sbin:%s swap -l -k' % os.environ['PATH'])
lines = out.strip().split('\n')[1:]
if not lines:
raise ValueError('no swap device(s) configured')
@ -35,12 +37,12 @@ class SunOSSpecificTestCase(unittest.TestCase):
self.assertEqual(psutil_swap.free, free)
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(SunOSSpecificTestCase))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -15,8 +15,10 @@ import sys
import time
import traceback
from test_psutil import (get_test_subprocess, reap_children, unittest)
from test_psutil import APPVEYOR, WINDOWS
from test_psutil import get_test_subprocess, reap_children, unittest
import mock
try:
import wmi
except ImportError:
@ -28,17 +30,18 @@ except ImportError:
win32api = win32con = None
from psutil._compat import PY3, callable, long
from psutil._pswindows import ACCESS_DENIED_SET
import _psutil_windows
import psutil
cext = psutil._psplatform.cext
def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
from psutil._pswindows import ACCESS_DENIED_SET
if err.errno in ACCESS_DENIED_SET:
raise psutil.AccessDenied(None, None)
if err.errno == errno.ESRCH:
@ -47,6 +50,7 @@ def wrap_exceptions(fun):
return wrapper
@unittest.skipUnless(WINDOWS, "not a Windows system")
class WindowsSpecificTestCase(unittest.TestCase):
@classmethod
@ -114,7 +118,9 @@ class WindowsSpecificTestCase(unittest.TestCase):
def test_process_exe(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
self.assertEqual(p.exe(), w.ExecutablePath)
# Note: wmi reports the exe as a lower case string.
# Being Windows paths case-insensitive we ignore that.
self.assertEqual(p.exe().lower(), w.ExecutablePath.lower())
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_cmdline(self):
@ -164,7 +170,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
# --- psutil namespace functions and constants tests
@unittest.skipUnless(hasattr(os, 'NUMBER_OF_PROCESSORS'),
@unittest.skipUnless('NUMBER_OF_PROCESSORS' in os.environ,
'NUMBER_OF_PROCESSORS env var is not available')
def test_cpu_count(self):
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
@ -188,20 +194,16 @@ class WindowsSpecificTestCase(unittest.TestCase):
# time.localtime(p.create_time()))
#
# Note: this test is not very reliable
@unittest.skipIf(wmi is None, "wmi module is not installed")
@unittest.skipIf(APPVEYOR, "test not relieable on appveyor")
def test_pids(self):
# Note: this test might fail if the OS is starting/killing
# other processes in the meantime
w = wmi.WMI().Win32_Process()
wmi_pids = [x.ProcessId for x in w]
wmi_pids.sort()
psutil_pids = psutil.pids()
psutil_pids.sort()
if wmi_pids != psutil_pids:
difference = \
filter(lambda x: x not in wmi_pids, psutil_pids) + \
filter(lambda x: x not in psutil_pids, wmi_pids)
self.fail("difference: " + str(difference))
wmi_pids = set([x.ProcessId for x in w])
psutil_pids = set(psutil.pids())
self.assertEqual(wmi_pids, psutil_pids)
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_disks(self):
@ -215,8 +217,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
break
try:
usage = psutil.disk_usage(ps_part.mountpoint)
except OSError:
err = sys.exc_info()[1]
except OSError as err:
if err.errno == errno.ENOENT:
# usually this is the floppy
break
@ -259,8 +260,6 @@ class WindowsSpecificTestCase(unittest.TestCase):
failures = []
for name in dir(psutil.Process):
if name.startswith('_') \
or name.startswith('set_') \
or name.startswith('get') \
or name in ('terminate', 'kill', 'suspend', 'resume',
'nice', 'send_signal', 'wait', 'children',
'as_dict'):
@ -282,29 +281,42 @@ class WindowsSpecificTestCase(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.skipUnless(WINDOWS, "not a Windows system")
class TestDualProcessImplementation(unittest.TestCase):
"""
Certain APIs on Windows have 2 internal implementations, one
based on documented Windows APIs, another one based
NtQuerySystemInformation() which gets called as fallback in
case the first fails because of limited permission error.
Here we test that the two methods return the exact same value,
see:
https://github.com/giampaolo/psutil/issues/304
"""
fun_names = [
# function name, tolerance
('proc_cpu_times', 0.2),
('proc_create_time', 0.5),
('proc_num_handles', 1), # 1 because impl #1 opens a handle
('proc_io_counters', 0),
('proc_memory_info', 1024), # KB
('proc_io_counters', 0),
]
def test_compare_values(self):
# Certain APIs on Windows have 2 internal implementations, one
# based on documented Windows APIs, another one based
# NtQuerySystemInformation() which gets called as fallback in
# case the first fails because of limited permission error.
# Here we test that the two methods return the exact same value,
# see:
# https://github.com/giampaolo/psutil/issues/304
def assert_ge_0(obj):
if isinstance(obj, tuple):
for value in obj:
self.assertGreaterEqual(value, 0)
self.assertGreaterEqual(value, 0, msg=obj)
elif isinstance(obj, (int, long, float)):
self.assertGreaterEqual(obj, 0)
else:
@ -322,55 +334,125 @@ class TestDualProcessImplementation(unittest.TestCase):
diff = abs(a - b)
self.assertLessEqual(diff, tolerance)
from psutil._pswindows import ntpinfo
failures = []
for name, tolerance in self.fun_names:
meth1 = wrap_exceptions(getattr(_psutil_windows, name))
meth2 = wrap_exceptions(getattr(_psutil_windows, name + '_2'))
for p in psutil.process_iter():
for p in psutil.process_iter():
try:
nt = ntpinfo(*cext.proc_info(p.pid))
except psutil.NoSuchProcess:
continue
assert_ge_0(nt)
for name, tolerance in self.fun_names:
if name == 'proc_memory_info' and p.pid == os.getpid():
continue
#
try:
ret1 = meth1(p.pid)
except psutil.NoSuchProcess:
if name == 'proc_create_time' and p.pid in (0, 4):
continue
except psutil.AccessDenied:
ret1 = None
#
meth = wrap_exceptions(getattr(cext, name))
try:
ret2 = meth2(p.pid)
except psutil.NoSuchProcess:
# this is supposed to fail only in case of zombie process
# never for permission error
ret = meth(p.pid)
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
# compare values
try:
if ret1 is None:
assert_ge_0(ret2)
else:
compare_with_tolerance(ret1, ret2, tolerance)
assert_ge_0(ret1)
assert_ge_0(ret2)
if name == 'proc_cpu_times':
compare_with_tolerance(ret[0], nt.user_time, tolerance)
compare_with_tolerance(ret[1],
nt.kernel_time, tolerance)
elif name == 'proc_create_time':
compare_with_tolerance(ret, nt.create_time, tolerance)
elif name == 'proc_num_handles':
compare_with_tolerance(ret, nt.num_handles, tolerance)
elif name == 'proc_io_counters':
compare_with_tolerance(ret[0], nt.io_rcount, tolerance)
compare_with_tolerance(ret[1], nt.io_wcount, tolerance)
compare_with_tolerance(ret[2], nt.io_rbytes, tolerance)
compare_with_tolerance(ret[3], nt.io_wbytes, tolerance)
elif name == 'proc_memory_info':
try:
rawtupl = cext.proc_memory_info_2(p.pid)
except psutil.NoSuchProcess:
continue
compare_with_tolerance(ret, rawtupl, tolerance)
except AssertionError:
trace = traceback.format_exc()
msg = '%s\npid=%s, method=%r, ret_1=%r, ret_2=%r' % (
trace, p.pid, name, ret1, ret2)
trace, p.pid, name, ret, nt)
failures.append(msg)
break
if failures:
self.fail('\n\n'.join(failures))
# ---
# same tests as above but mimicks the AccessDenied failure of
# the first (fast) method failing with AD.
# TODO: currently does not take tolerance into account.
def test_name(self):
name = psutil.Process().name()
with mock.patch("psutil._psplatform.cext.proc_exe",
side_effect=psutil.AccessDenied(os.getpid())) as fun:
psutil.Process().name() == name
assert fun.called
def test_memory_info(self):
mem = psutil.Process().memory_info()
with mock.patch("psutil._psplatform.cext.proc_memory_info",
side_effect=OSError(errno.EPERM, "msg")) as fun:
psutil.Process().memory_info() == mem
assert fun.called
def test_create_time(self):
ctime = psutil.Process().create_time()
with mock.patch("psutil._psplatform.cext.proc_create_time",
side_effect=OSError(errno.EPERM, "msg")) as fun:
psutil.Process().create_time() == ctime
assert fun.called
def test_cpu_times(self):
cpu_times = psutil.Process().cpu_times()
with mock.patch("psutil._psplatform.cext.proc_cpu_times",
side_effect=OSError(errno.EPERM, "msg")) as fun:
psutil.Process().cpu_times() == cpu_times
assert fun.called
def test_io_counters(self):
io_counters = psutil.Process().io_counters()
with mock.patch("psutil._psplatform.cext.proc_io_counters",
side_effect=OSError(errno.EPERM, "msg")) as fun:
psutil.Process().io_counters() == io_counters
assert fun.called
def test_num_handles(self):
io_counters = psutil.Process().io_counters()
with mock.patch("psutil._psplatform.cext.proc_io_counters",
side_effect=OSError(errno.EPERM, "msg")) as fun:
psutil.Process().io_counters() == io_counters
assert fun.called
# --- other tests
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_zombies(self):
# test that NPS is raised by the 2nd implementation in case a
# process no longer exists
ZOMBIE_PID = max(psutil.pids()) + 5000
for name, _ in self.fun_names:
meth = wrap_exceptions(getattr(_psutil_windows, name))
meth = wrap_exceptions(getattr(cext, name))
self.assertRaises(psutil.NoSuchProcess, meth, ZOMBIE_PID)
def test_main():
def main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(WindowsSpecificTestCase))
test_suite.addTest(unittest.makeSuite(TestDualProcessImplementation))
@ -378,5 +460,5 @@ def test_main():
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

View File

@ -10,6 +10,7 @@ functions many times and compare process memory usage before and
after the calls. It might produce false positives.
"""
import functools
import gc
import os
import socket
@ -17,20 +18,20 @@ import sys
import threading
import time
import psutil
import psutil._common
from psutil._compat import xrange, callable
from test_psutil import (WINDOWS, POSIX, OSX, LINUX, SUNOS, BSD, TESTFN,
RLIMIT_SUPPORT, TRAVIS)
from test_psutil import (reap_children, supports_ipv6, safe_remove,
get_test_subprocess)
if sys.version_info < (2, 7):
import unittest2 as unittest # https://pypi.python.org/pypi/unittest2
else:
import unittest
import psutil
import psutil._common
from psutil._compat import callable, xrange
from test_psutil import (WINDOWS, POSIX, OSX, LINUX, SUNOS, TESTFN,
RLIMIT_SUPPORT)
from test_psutil import (reap_children, supports_ipv6, safe_remove,
get_test_subprocess)
LOOPS = 1000
TOLERANCE = 4096
@ -43,7 +44,7 @@ def skip_if_linux():
class Base(unittest.TestCase):
proc = psutil.Process(os.getpid())
proc = psutil.Process()
def execute(self, function, *args, **kwargs):
def call_many_times():
@ -73,7 +74,7 @@ class Base(unittest.TestCase):
# Let's keep calling fun for 3 more seconds and fail if
# we notice any difference.
stop_at = time.time() + 3
while 1:
while True:
self.call(function, *args, **kwargs)
if time.time() >= stop_at:
break
@ -85,10 +86,14 @@ class Base(unittest.TestCase):
self.fail("rss2=%s, rss3=%s, difference=%s"
% (rss2, rss3, difference))
def get_mem(self):
return psutil.Process(os.getpid()).memory_info()[0]
def execute_w_exc(self, exc, function, *args, **kwargs):
kwargs['_exc'] = exc
self.execute(function, *args, **kwargs)
def call(self, *args, **kwargs):
def get_mem(self):
return psutil.Process().memory_info()[0]
def call(self, function, *args, **kwargs):
raise NotImplementedError("must be implemented in subclass")
@ -102,12 +107,25 @@ class TestProcessObjectLeaks(Base):
reap_children()
def call(self, function, *args, **kwargs):
try:
obj = getattr(self.proc, function)
if callable(obj):
obj(*args, **kwargs)
except psutil.Error:
pass
if callable(function):
if '_exc' in kwargs:
exc = kwargs.pop('_exc')
self.assertRaises(exc, function, *args, **kwargs)
else:
try:
function(*args, **kwargs)
except psutil.Error:
pass
else:
meth = getattr(self.proc, function)
if '_exc' in kwargs:
exc = kwargs.pop('_exc')
self.assertRaises(exc, meth, *args, **kwargs)
else:
try:
meth(*args, **kwargs)
except psutil.Error:
pass
@skip_if_linux()
def test_name(self):
@ -143,7 +161,7 @@ class TestProcessObjectLeaks(Base):
self.execute('nice')
def test_nice_set(self):
niceness = psutil.Process(os.getpid()).nice()
niceness = psutil.Process().nice()
self.execute('nice', niceness)
@unittest.skipUnless(hasattr(psutil.Process, 'ionice'),
@ -155,16 +173,20 @@ class TestProcessObjectLeaks(Base):
"Linux and Windows Vista only")
def test_ionice_set(self):
if WINDOWS:
value = psutil.Process(os.getpid()).ionice()
value = psutil.Process().ionice()
self.execute('ionice', value)
else:
from psutil._pslinux import cext
self.execute('ionice', psutil.IOPRIO_CLASS_NONE)
fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0)
self.execute_w_exc(OSError, fun)
@unittest.skipIf(OSX, "feature not supported on this platform")
@unittest.skipIf(OSX or SUNOS, "feature not supported on this platform")
@skip_if_linux()
def test_io_counters(self):
self.execute('io_counters')
@unittest.skipUnless(WINDOWS, "not worth being tested on posix")
def test_username(self):
self.execute('username')
@ -215,23 +237,24 @@ class TestProcessObjectLeaks(Base):
def test_cwd(self):
self.execute('cwd')
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
@unittest.skipUnless(WINDOWS or LINUX or BSD,
"Windows or Linux or BSD only")
def test_cpu_affinity_get(self):
self.execute('cpu_affinity')
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
@unittest.skipUnless(WINDOWS or LINUX or BSD,
"Windows or Linux or BSD only")
def test_cpu_affinity_set(self):
affinity = psutil.Process(os.getpid()).cpu_affinity()
affinity = psutil.Process().cpu_affinity()
self.execute('cpu_affinity', affinity)
if not TRAVIS:
self.execute_w_exc(ValueError, 'cpu_affinity', [-1])
@skip_if_linux()
def test_open_files(self):
safe_remove(TESTFN) # needed after UNIX socket test has run
f = open(TESTFN, 'w')
try:
with open(TESTFN, 'w'):
self.execute('open_files')
finally:
f.close()
# OSX implementation is unbelievably slow
@unittest.skipIf(OSX, "OSX implementation is too slow")
@ -251,6 +274,7 @@ class TestProcessObjectLeaks(Base):
def test_rlimit_set(self):
limit = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)
self.execute('rlimit', psutil.RLIMIT_NOFILE, limit)
self.execute_w_exc(OSError, 'rlimit', -1)
@skip_if_linux()
# Windows implementation is based on a single system-wide function
@ -301,6 +325,12 @@ class TestProcessObjectLeaksZombie(TestProcessObjectLeaks):
"""
proc = DEAD_PROC
def call(self, *args, **kwargs):
try:
TestProcessObjectLeaks.call(self, *args, **kwargs)
except psutil.NoSuchProcess:
pass
if not POSIX:
def test_kill(self):
self.execute('kill')
@ -325,9 +355,8 @@ class TestModuleFunctionsLeaks(Base):
gc.collect()
def call(self, function, *args, **kwargs):
obj = getattr(psutil, function)
if callable(obj):
obj(*args, **kwargs)
fun = getattr(psutil, function)
fun(*args, **kwargs)
@skip_if_linux()
def test_cpu_count_logical(self):
@ -393,8 +422,15 @@ class TestModuleFunctionsLeaks(Base):
def test_net_connections(self):
self.execute('net_connections')
def test_net_if_addrs(self):
self.execute('net_if_addrs')
def test_main():
@unittest.skipIf(TRAVIS, "EPERM on travis")
def test_net_if_stats(self):
self.execute('net_if_stats')
def main():
test_suite = unittest.TestSuite()
tests = [TestProcessObjectLeaksZombie,
TestProcessObjectLeaks,
@ -405,5 +441,5 @@ def test_main():
return result.wasSuccessful()
if __name__ == '__main__':
if not test_main():
if not main():
sys.exit(1)

File diff suppressed because it is too large Load Diff

View File

@ -9,16 +9,24 @@ envlist = py26, py27, py32, py33, py34
[testenv]
deps =
pytest
flake8
pytest
py26: ipaddress
py26: mock==1.0.1
py26: unittest2
py27: ipaddress
py27: mock
py32: ipaddress
py32: mock
py33: ipaddress
setenv =
PYTHONPATH = {toxinidir}/test
commands =
py.test {posargs}
flake8 --exclude=build,.tox,.git
git ls-files | grep \\.py$ | xargs flake8
[testenv:py26]
deps =
flake8
pytest
unittest2
# suppress "WARNING: 'git' command found but not installed in testenv
whitelist_externals = git
usedevelop = True