Bug 930808 - Upgrade to psutil 2.1.3; r=glandium

psutil 2.1.3 is replacing psutil 1.0.1. There are numerous bug fixes and
feature enhancements in psutil worth obtaining.

Source code was obtained from
https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz and
uncompressed into python/psutil without modification except for the
removal of the egg-info directory and the .travis.yml file.

--HG--
extra : rebase_source : 90b02e514e5dd1249d97d83223ef8fcf20c9da94
extra : histedit_source : 2e96344e1796b6156ccf279684687b2e8995be92
This commit is contained in:
Gregory Szorc 2014-12-23 10:45:15 -08:00
parent fa97bf9388
commit 9ee889e5ba
88 changed files with 13624 additions and 7313 deletions

View File

@ -1,22 +1,24 @@
Intro
=====
We would like to recognize some of the people who have been instrumental in the
I would like to recognize some of the people who have been instrumental in the
development of psutil.
I'm sure we are forgetting some people (feel free to email us), but here is a
I'm sure I'm forgetting some people (feel free to email me), but here is a
short list.
It's modeled after the Linux CREDITS file where the fields are:
name (N), e-mail (E), web-address (W), country (C), description (D), (I) issues
(issue tracker is at http://code.google.com/p/psutil/issues/list).
(issue tracker is at https://github.com/giampaolo/psutil/issues).
Really thanks to all of you.
- Giampaolo
Author
======
N: Giampaolo Rodola'
C: Italy
E: g.rodola@gmail.com
W: http://www.linkedin.com/in/grodola
W: http://grodola.blogspot.com/
Contributors
============
@ -24,11 +26,12 @@ Contributors
N: Jay Loden
C: NJ, USA
E: jloden@gmail.com
D: original co-author, initial design/bootstrap and continuing bug fixes
D: original co-author, initial design/bootstrap and occasional bug fixes
W: http://www.jayloden.com
N: Jeremy Whitlock
E: jcscoobyrs@gmail.com
D: great help with OSX C development.
I: 125, 150, 174, 206
N: wj32
@ -39,7 +42,7 @@ I: 114, 115
N: Yan Raber
C: Bologna, Italy
E: yanraber@gmail.com
D: help on Windows development
D: help on Windows development (initial version of Process.username())
N: Justin Venus
E: justin.venus@gmail.com
@ -49,7 +52,9 @@ I: 18
N: Dave Daeschler
C: USA
E: david.daeschler@gmail.com
D: initial design/bootstrap and continuing bug fixes
W: http://daviddaeschler.com
D: some contributions to initial design/bootstrap plus occasional bug fixing
I: 522, 536
N: cjgohlke
E: cjgohlke@gmail.com
@ -180,3 +185,79 @@ I: 386
N: Adrien Fallou
I: 224
N: Gisle Vanem
E: gisle.vanem@gmail.com
I: 411
N: thepyr0
E: thepyr0@gmail.com
I: 414
N: John Pankov
E: john.pankov@gmail.com
I: 435
N: Matt Good
W: http://matt-good.net/
I: 438
N: Ulrich Klank
E: ulrich.klank@scitics.de
I: 448
N: Josiah Carlson
E: josiah.carlson@gmail.com
I: 451, 452
N: Raymond Hettinger
D: namedtuple and lru_cache backward compatible implementations.
N: Jason Kirtland
D: backward compatible implementation of collections.defaultdict.
M: Ken Seeho
D: @cached_property decorator
N: crusaderky
E: crusaderky@gmail.com
I: 470, 477
E: alex@mroja.net
I: 471
N: Gautam Singh
E: gautam.singh@gmail.com
I: 466
E: lhn@hupfeldtit.dk
I: 476, 479
N: Francois Charron
E: francois.charron.1@gmail.com
I: 474
N: Naveed Roudsari
E: naveed.roudsari@gmail.com
I: 421
N: Alexander Grothe
E: Alexander.Grothe@gmail.com
I: 497
N: Szigeti Gabor Niif
E: szigeti.gabor.niif@gmail.com
I: 446
N: msabramo
E: msabramo@gmail.com
I: 492
N: Jeff Tang
W: https://github.com/mrjefftang
I: 340, 529
N: Yaolong Huang
E: airekans@gmail.com
W: http://airekans.github.io/
I: 530

View File

@ -1,574 +0,0 @@
Bug tracker at http://code.google.com/p/psutil/issues
1.0.1 - 2013-07-12
------------------
BUG FIXES
* #405: network_io_counters(pernic=True) no longer works as intended in 1.0.0.
1.0.0 - 2013-07-10
------------------
NEW FEATURES
* #18: Solaris support (yay!) (thanks Justin Venus)
* #367: Process.get_connections() 'status' strings are now constants.
* #380: test suite exits with non-zero on failure. (patch by floppymaster)
* #391: extensively use unittest2 module in unit tests and provide
workarounds if this is not installed on python < 2.7.
BUG FIXES
* #374: [Windows] negative memory usage reported when processes use a lot of
memory.
* #379: [Linux] Process.get_memory_maps() may raise ValueError.
* #394: [OSX] Mapped memory regions report incorrect file name.
* #404: [Linux] sched_*affinity() are implicitly declared. (patch by Arfrever)
API CHANGES
* Process.get_connections() 'status' field is no longer a string but a constant
object (psutil.CONN_*).
* Process.get_connections() 'local_address' and 'remote_address' fields renamed
to 'laddr' and 'raddr'.
* psutil.network_io_counters() renamed to psutil.net_io_counters().
0.7.1 - 2013-05-03
------------------
BUG FIXES:
* #325: [BSD] psutil.virtual_memory() can raise SystemError.
(patch by Jan Beich)
* #370: [BSD] Process.get_connections() requires root. (patch by John Baldwin)
* #372: [BSD] different process methods raise NoSuchProcess instead of
AccessDenied.
0.7.0 - 2013-04-12
------------------
NEW FEATURES
* #233: code migrated to Mercurial (yay!)
* #246: psutil.error module is deprecated and scheduled for removal.
* #328: [Windows] process IO nice/priority support.
* #359: psutil.get_boot_time()
* #361: [Linux] psutil.cpu_times() now includes new 'steal', 'guest' and
'guest_nice' fields available on recent Linux kernels.
Also, psutil.cpu_percent() is more accurate.
* #362: cpu_times_percent() (per-CPU-time utilization as a percentage)
BUG FIXES
* #234: [Windows] disk_io_counters() fails to list certain disks.
* #264: [Windows] use of psutil.disk_partitions() may cause a message box to
appear.
* #313: [Linux] psutil.virtual_memory() and psutil.swap_memory() can crash on
certain exotic Linux flavors having an incomplete /proc interface.
If that's the case we now set the unretrievable stats to 0 and raise a
RuntimeWarning.
* #315: [OSX] fix some compilation warnings.
* #317: [Windows] cannot set process CPU affinity above 31 cores.
* #319: [Linux] process get_memory_maps() raises KeyError 'Anonymous' on Debian
squeeze.
* #321: [UNIX] Process.ppid property is no longer cached as the kernel may set
the ppid to 1 in case of a zombie process.
* #323: [OSX] disk_io_counters()'s read_time and write_time parameters were
reporting microseconds not milliseconds. (patch by Gregory Szorc)
* #331: Process cmdline is no longer cached after first acces as it may change.
* #333: [OSX] Leak of Mach ports on OS X (patch by rsesek@google.com)
* #337: [Linux] process methods not working because of a poor /proc
implementation will raise NotImplementedError rather than RuntimeError
and Process.as_dict() will not blow up. (patch by Curtin1060)
* #338: [Linux] disk_io_counters() fails to find some disks.
* #339: [FreeBSD] get_pid_list() can allocate all the memory on system.
* #341: [Linux] psutil might crash on import due to error in retrieving system
terminals map.
* #344: [FreeBSD] swap_memory() might return incorrect results due to
kvm_open(3) not being called. (patch by Jean Sebastien)
* #338: [Linux] disk_io_counters() fails to find some disks.
* #351: [Windows] if psutil is compiled with mingw32 (provided installers for
py2.4 and py2.5 are) disk_io_counters() will fail. (Patch by m.malycha)
* #353: [OSX] get_users() returns an empty list on OSX 10.8.
* #356: Process.parent now checks whether parent PID has been reused in which
case returns None.
* #365: Process.set_nice() should check PID has not been reused by another
process.
* #366: [FreeBSD] get_memory_maps(), get_num_fds(), get_open_files() and
getcwd() Process methods raise RuntimeError instead of AccessDenied.
API CHANGES
* Process.cmdline property is no longer cached after first access.
* Process.ppid property is no longer cached after first access.
* [Linux] Process methods not working because of a poor /proc implementation
will raise NotImplementedError instead of RuntimeError.
* psutil.error module is deprecated and scheduled for removal.
0.6.1 - 2012-08-16
------------------
NEW FEATURES
* #316: process cmdline property now makes a better job at guessing the process
executable from the cmdline.
BUG FIXES
* #316: process exe was resolved in case it was a symlink.
* #318: python 2.4 compatibility was broken.
API CHANGES
* process exe can now return an empty string instead of raising AccessDenied.
* process exe is no longer resolved in case it's a symlink.
0.6.0 - 2012-08-13
------------------
NEW FEATURES
* #216: [POSIX] get_connections() UNIX sockets support.
* #220: [FreeBSD] get_connections() has been rewritten in C and no longer
requires lsof.
* #222: [OSX] add support for process cwd.
* #261: process extended memory info.
* #295: [OSX] process executable path is now determined by asking the OS
instead of being guessed from process cmdline.
* #297: [OSX] the Process methods below were always raising AccessDenied for
any process except the current one. Now this is no longer true. Also
they are 2.5x faster.
- name
- get_memory_info()
- get_memory_percent()
- get_cpu_times()
- get_cpu_percent()
- get_num_threads()
* #300: examples/pmap.py script.
* #301: process_iter() now yields processes sorted by their PIDs.
* #302: process number of voluntary and involuntary context switches.
* #303: [Windows] the Process methods below were always raising AccessDenied
for any process not owned by current user. Now this is no longer true:
- create_time
- get_cpu_times()
- get_cpu_percent()
- get_memory_info()
- get_memory_percent()
- get_num_handles()
- get_io_counters()
* #305: add examples/netstat.py script.
* #311: system memory functions has been refactorized and rewritten and now
provide a more detailed and consistent representation of the system
memory. New psutil.virtual_memory() function provides the following
memory amounts:
- total
- available
- percent
- used
- active [POSIX]
- inactive [POSIX]
- buffers (BSD, Linux)
- cached (BSD, OSX)
- wired (OSX, BSD)
- shared [FreeBSD]
New psutil.swap_memory() provides:
- total
- used
- free
- percent
- sin (no. of bytes the system has swapped in from disk (cumulative))
- sout (no. of bytes the system has swapped out from disk (cumulative))
All old memory-related functions are deprecated.
Also two new example scripts were added: free.py and meminfo.py.
* #312: psutil.network_io_counters() namedtuple includes 4 new fields:
errin, errout dropin and dropout, reflecting the number of packets
dropped and with errors.
BUGFIXES
* #298: [OSX and BSD] memory leak in get_num_fds().
* #299: potential memory leak every time PyList_New(0) is used.
* #303: [Windows] potential heap corruption in get_num_threads() and
get_status() Process methods.
* #305: [FreeBSD] psutil can't compile on FreeBSD 9 due to removal of utmp.h.
* #306: at C level, errors are not checked when invoking Py* functions which
create or manipulate Python objects leading to potential memory related
errors and/or segmentation faults.
* #307: [FreeBSD] values returned by psutil.network_io_counters() are wrong.
* #308: [BSD / Windows] psutil.virtmem_usage() wasn't actually returning
information about swap memory usage as it was supposed to do. It does
now.
* #309: get_open_files() might not return files which can not be accessed
due to limited permissions. AccessDenied is now raised instead.
API CHANGES
* psutil.phymem_usage() is deprecated (use psutil.virtual_memory())
* psutil.virtmem_usage() is deprecated (use psutil.swap_memory())
* psutil.phymem_buffers() on Linux is deprecated (use psutil.virtual_memory())
* psutil.cached_phymem() on Linux is deprecated (use psutil.virtual_memory())
* [Windows and BSD] psutil.virtmem_usage() now returns information about swap
memory instead of virtual memory.
0.5.1 - 2012-06-29
------------------
NEW FEATURES
* #293: [Windows] process executable path is now determined by asking the OS
instead of being guessed from process cmdline.
BUGFIXES
* #292: [Linux] race condition in process files/threads/connections.
* #294: [Windows] Process CPU affinity is only able to set CPU #0.
0.5.0 - 2012-06-27
------------------
NEW FEATURES
* #195: [Windows] number of handles opened by process.
* #209: psutil.disk_partitions() now provides also mount options.
* #229: list users currently connected on the system (psutil.get_users()).
* #238: [Linux, Windows] process CPU affinity (get and set).
* #242: Process.get_children(recursive=True): return all process
descendants.
* #245: [POSIX] Process.wait() incrementally consumes less CPU cycles.
* #257: [Windows] removed Windows 2000 support.
* #258: [Linux] Process.get_memory_info() is now 0.5x faster.
* #260: process's mapped memory regions. (Windows patch by wj32.64, OSX patch
by Jeremy Whitlock)
* #262: [Windows] psutil.disk_partitions() was slow due to inspecting the
floppy disk drive also when "all" argument was False.
* #273: psutil.get_process_list() is deprecated.
* #274: psutil no longer requires 2to3 at installation time in order to work
with Python 3.
* #278: new Process.as_dict() method.
* #281: ppid, name, exe, cmdline and create_time properties of Process class
are now cached after being accessed.
* #282: psutil.STATUS_* constants can now be compared by using their string
representation.
* #283: speedup Process.is_running() by caching its return value in case the
process is terminated.
* #284: [POSIX] per-process number of opened file descriptors.
* #287: psutil.process_iter() now caches Process instances between calls.
* #290: Process.nice property is deprecated in favor of new get_nice() and
set_nice() methods.
BUGFIXES
* #193: psutil.Popen constructor can throw an exception if the spawned process
terminates quickly.
* #240: [OSX] incorrect use of free() for Process.get_connections().
* #244: [POSIX] Process.wait() can hog CPU resources if called against a
process which is not our children.
* #248: [Linux] psutil.network_io_counters() might return erroneous NIC names.
* #252: [Windows] process getcwd() erroneously raise NoSuchProcess for
processes owned by another user. It now raises AccessDenied instead.
* #266: [Windows] psutil.get_pid_list() only shows 1024 processes.
(patch by Amoser)
* #267: [OSX] Process.get_connections() - an erroneous remote address was
returned. (Patch by Amoser)
* #272: [Linux] Porcess.get_open_files() - potential race condition can lead to
unexpected NoSuchProcess exception. Also, we can get incorrect reports
of not absolutized path names.
* #275: [Linux] Process.get_io_counters() erroneously raise NoSuchProcess on
old Linux versions. Where not available it now raises
NotImplementedError.
* #286: Process.is_running() doesn't actually check whether PID has been
reused.
* #314: Process.get_children() can sometimes return non-children.
API CHANGES
* Process.nice property is deprecated in favor of new get_nice() and set_nice()
methods.
* psutil.get_process_list() is deprecated.
* ppid, name, exe, cmdline and create_time properties of Process class are now
cached after being accessed, meaning NoSuchProcess will no longer be raised
in case the process is gone in the meantime.
* psutil.STATUS_* constants can now be compared by using their string
representation.
0.4.1 - 2011-12-14
------------------
BUGFIXES
* #228: some example scripts were not working with python 3.
* #230: [Windows / OSX] memory leak in Process.get_connections().
* #232: [Linux] psutil.phymem_usage() can report erroneous values which are
different than "free" command.
* #236: [Windows] memory/handle leak in Process's get_memory_info(),
suspend() and resume() methods.
0.4.0 - 2011-10-29
------------------
NEW FEATURES
* #150: network I/O counters. (OSX and Windows patch by Jeremy Whitlock)
* #154: [FreeBSD] add support for process getcwd()
* #157: [Windows] provide installer for Python 3.2 64-bit.
* #198: Process.wait(timeout=0) can now be used to make wait() return
immediately.
* #206: disk I/O counters. (OSX and Windows patch by Jeremy Whitlock)
* #213: examples/iotop.py script.
* #217: Process.get_connections() now has a "kind" argument to filter
for connections with different criteria.
* #221: [FreeBSD] Process.get_open_files has been rewritten in C and no longer
relies on lsof.
* #223: examples/top.py script.
* #227: examples/nettop.py script.
BUGFIXES
* #135: [OSX] psutil cannot create Process object.
* #144: [Linux] no longer support 0 special PID.
* #188: [Linux] psutil import error on Linux ARM architectures.
* #194: [POSIX] psutil.Process.get_cpu_percent() now reports a percentage over
100 on multicore processors.
* #197: [Linux] Process.get_connections() is broken on platforms not supporting
IPv6.
* #200: [Linux] psutil.NUM_CPUS not working on armel and sparc architectures
and causing crash on module import.
* #201: [Linux] Process.get_connections() is broken on big-endian
architectures.
* #211: Process instance can unexpectedly raise NoSuchProcess if tested for
equality with another object.
* #218: [Linux] crash at import time on Debian 64-bit because of a missing line
in /proc/meminfo.
* #226: [FreeBSD] crash at import time on FreeBSD 7 and minor.
0.3.0 - 2011-07-08
------------------
NEW FEATURES
* #125: system per-cpu percentage utilization and times.
* #163: per-process associated terminal (TTY).
* #171: added get_phymem() and get_virtmem() functions returning system
memory information (total, used, free) and memory percent usage.
total_* avail_* and used_* memory functions are deprecated.
* #172: disk usage statistics.
* #174: mounted disk partitions.
* #179: setuptools is now used in setup.py
BUGFIXES
* #159: SetSeDebug() does not close handles or unset impersonation on return.
* #164: [Windows] wait function raises a TimeoutException when a process
returns -1 .
* #165: process.status raises an unhandled exception.
* #166: get_memory_info() leaks handles hogging system resources.
* #168: psutil.cpu_percent() returns erroneous results when used in
non-blocking mode. (patch by Philip Roberts)
* #178: OSX - Process.get_threads() leaks memory
* #180: [Windows] Process's get_num_threads() and get_threads() methods can
raise NoSuchProcess exception while process still exists.
0.2.1 - 2011-03-20
------------------
NEW FEATURES
* #64: per-process I/O counters.
* #116: per-process wait() (wait for process to terminate and return its exit
code).
* #134: per-process get_threads() returning information (id, user and kernel
times) about threads opened by process.
* #136: process executable path on FreeBSD is now determined by asking the
kernel instead of guessing it from cmdline[0].
* #137: per-process real, effective and saved user and group ids.
* #140: system boot time.
* #142: per-process get and set niceness (priority).
* #143: per-process status.
* #147: per-process I/O nice (priority) - Linux only.
* #148: psutil.Popen class which tidies up subprocess.Popen and psutil.Process
in a unique interface.
* #152: [OSX] get_process_open_files() implementation has been rewritten
in C and no longer relies on lsof resulting in a 3x speedup.
* #153: [OSX] get_process_connection() implementation has been rewritten
in C and no longer relies on lsof resulting in a 3x speedup.
BUGFIXES
* #83: process cmdline is empty on OSX 64-bit.
* #130: a race condition can cause IOError exception be raised on
Linux if process disappears between open() and subsequent read() calls.
* #145: WindowsError was raised instead of psutil.AccessDenied when using
process resume() or suspend() on Windows.
* #146: 'exe' property on Linux can raise TypeError if path contains NULL
bytes.
* #151: exe and getcwd() for PID 0 on Linux return inconsistent data.
API CHANGES
* Process "uid" and "gid" properties are deprecated in favor of "uids" and
"gids" properties.
0.2.0 - 2010-11-13
------------------
NEW FEATURES
* #79: per-process open files.
* #88: total system physical cached memory.
* #88: total system physical memory buffers used by the kernel.
* #91: per-process send_signal() and terminate() methods.
* #95: NoSuchProcess and AccessDenied exception classes now provide "pid",
"name" and "msg" attributes.
* #97: per-process children.
* #98: Process.get_cpu_times() and Process.get_memory_info now return
a namedtuple instead of a tuple.
* #103: per-process opened TCP and UDP connections.
* #107: add support for Windows 64 bit. (patch by cjgohlke)
* #111: per-process executable name.
* #113: exception messages now include process name and pid.
* #114: process username Windows implementation has been rewritten in pure
C and no longer uses WMI resulting in a big speedup. Also, pywin32 is no
longer required as a third-party dependancy. (patch by wj32)
* #117: added support for Windows 2000.
* #123: psutil.cpu_percent() and psutil.Process.cpu_percent() accept a
new 'interval' parameter.
* #129: per-process number of threads.
BUGFIXES
* #80: fixed warnings when installing psutil with easy_install.
* #81: psutil fails to compile with Visual Studio.
* #94: suspend() raises OSError instead of AccessDenied.
* #86: psutil didn't compile against FreeBSD 6.x.
* #102: orphaned process handles obtained by using OpenProcess in C were
left behind every time Process class was instantiated.
* #111: path and name Process properties report truncated or erroneous
values on UNIX.
* #120: cpu_percent() always returning 100% on OS X.
* #112: uid and gid properties don't change if process changes effective
user/group id at some point.
* #126: ppid, uid, gid, name, exe, cmdline and create_time properties are
no longer cached and correctly raise NoSuchProcess exception if the process
disappears.
API CHANGES
* psutil.Process.path property is deprecated and works as an alias for "exe"
property.
* psutil.Process.kill(): signal argument was removed - to send a signal to the
process use send_signal(signal) method instead.
* psutil.Process.get_memory_info() returns a nametuple instead of a tuple.
* psutil.cpu_times() returns a nametuple instead of a tuple.
* New psutil.Process methods: get_open_files(), get_connections(),
send_signal() and terminate().
* ppid, uid, gid, name, exe, cmdline and create_time properties are no longer
cached and raise NoSuchProcess exception if process disappears.
* psutil.cpu_percent() no longer returns immediately (see issue 123).
* psutil.Process.get_cpu_percent() and psutil.cpu_percent() no longer returns
immediately by default (see issue 123).
0.1.3 - 2010-03-02
------------------
NEW FEATURES
* #14: per-process username
* #51: per-process current working directory (Windows and Linux only)
* #59: Process.is_running() is now 10 times faster
* #61: added supoprt for FreeBSD 64 bit
* #71: implemented suspend/resume process
* #75: python 3 support
BUGFIXES
* #36: process cpu_times() and memory_info() functions succeeded also for
dead processes while a NoSuchProcess exception is supposed to be raised.
* #48: incorrect size for mib array defined in getcmdargs for BSD
* #49: possible memory leak due to missing free() on error condition on
* #50: fixed getcmdargs() memory fragmentation on BSD
* #55: test_pid_4 was failing on Windows Vista
* #57: some unit tests were failing on systems where no swap memory is
available
* #58: is_running() is now called before kill() to make sure we are going
to kill the correct process.
* #73: virtual memory size reported on OS X includes shared library size
* #77: NoSuchProcess wasn't raised on Process.create_time if kill() was
used first.
0.1.2 - 2009-05-06
------------------
NEW FEATURES
* #32: Per-process CPU user/kernel times
* #33: Process create time
* #34: Per-process CPU utilization percentage
* #38: Per-process memory usage (bytes)
* #41: Per-process memory utilization (percent)
* #39: System uptime
* #43: Total system virtual memory
* #46: Total system physical memory
* #44: Total system used/free virtual and physical memory
BUGFIXES
* #36: [Windows] NoSuchProcess not raised when accessing timing methods.
* #40: test_get_cpu_times() failing on FreeBSD and OS X.
* #42: [Windows] get_memory_percent() raises AccessDenied.
0.1.1 - 2009-03-06
------------------
NEW FEATURES
* #4: FreeBSD support for all functions of psutil
* #9: Process.uid and Process.gid now retrieve process UID and GID.
* #11: Support for parent/ppid - Process.parent property returns a
Process object representing the parent process, and Process.ppid returns
the parent PID.
* #12 & 15:
NoSuchProcess exception now raised when creating an object
for a nonexistent process, or when retrieving information about a process
that has gone away.
* #21: AccessDenied exception created for raising access denied errors
from OSError or WindowsError on individual platforms.
* #26: psutil.process_iter() function to iterate over processes as
Process objects with a generator.
* #?: Process objects can now also be compared with == operator for equality
(PID, name, command line are compared).
BUGFIXES
* #16: [Windows] Special case for "System Idle Process" (PID 0) which
otherwise would return an "invalid parameter" exception.
* #17: get_process_list() ignores NoSuchProcess and AccessDenied
exceptions during building of the list.
* #22: [Windows] Process(0).kill() was failing with an unset exception.
* #23: Special case for pid_exists(0)
* #24: [Windows] Process(0).kill() now raises AccessDenied exception instead of
WindowsError.
* #30: psutil.get_pid_list() was returning two instances of PID 0 on OS
X and FreeBSD platforms.
0.1.0 - 2009-01-27
------------------
* Initial release.

885
python/psutil/HISTORY.rst Normal file
View File

@ -0,0 +1,885 @@
Bug tracker at https://github.com/giampaolo/psutil/issues
2.1.3 2014-09-26
================
**Bug fixes**
- #536: [Linux]: fix "undefined symbol: CPU_ALLOC" compilation error.
2.1.2 - 2014-09-21
==================
**Enhancements**
- #407: project moved from Google Code to Github; code moved from Mercurial
to Git.
- #492: use tox to run tests on multiple python versions. (patch by msabramo)
- #505: [Windows] distribution as wheel packages.
- #511: new examples/ps.py sample code.
**Bug fixes**
- #340: [Windows] Process.get_open_files() no longer hangs. (patch by
Jeff Tang)
- #501: [Windows] disk_io_counters() may return negative values.
- #503: [Linux] in rare conditions Process exe(), open_files() and
connections() methods can raise OSError(ESRCH) instead of NoSuchProcess.
- #504: [Linux] can't build RPM packages via setup.py
- #506: [Linux] python 2.4 support was broken.
- #522: [Linux] Process.cpu_affinity() might return EINVAL. (patch by David
Daeschler)
- #529: [Windows] Process.exe() may raise unhandled WindowsError exception
for PIDs 0 and 4. (patch by Jeff Tang)
- #530: [Linux] psutil.disk_io_counters() may crash on old Linux distros
(< 2.6.5) (patch by Yaolong Huang)
- #533: [Linux] Process.memory_maps() may raise TypeError on old Linux distros.
2.1.1 - 2014-04-30
==================
**Bug fixes**
- #446: [Windows] fix encoding error when using net_io_counters() on Python 3.
(patch by Szigeti Gabor Niif)
- #460: [Windows] net_io_counters() wraps after 4G.
- #491: [Linux] psutil.net_connections() exceptions. (patch by Alexander Grothe)
2.1.0 - 2014-04-08
==================
**Enhancements**
- #387: system-wide open connections a-la netstat.
**Bug fixes**
- #421: [Solaris] psutil does not compile on SunOS 5.10 (patch by Naveed
Roudsari)
- #489: [Linux] psutil.disk_partitions() return an empty list.
2.0.0 - 2014-03-10
==================
**Enhancements**
- #424: [Windows] installer for Python 3.X 64 bit.
- #427: number of logical and physical CPUs (psutil.cpu_count()).
- #447: psutil.wait_procs() timeout parameter is now optional.
- #452: make Process instances hashable and usable with set()s.
- #453: tests on Python < 2.7 require unittest2 module.
- #459: add a make file for running tests and other repetitive tasks (also
on Windows).
- #463: make timeout parameter of cpu_percent* functions default to 0.0 'cause
it's a common trap to introduce slowdowns.
- #468: move documentation to readthedocs.com.
- #477: process cpu_percent() is about 30% faster. (suggested by crusaderky)
- #478: [Linux] almost all APIs are about 30% faster on Python 3.X.
- #479: long deprecated psutil.error module is gone; exception classes now
live in "psutil" namespace only.
**Bug fixes**
- #193: psutil.Popen constructor can throw an exception if the spawned process
terminates quickly.
- #340: [Windows] process get_open_files() no longer hangs. (patch by
jtang@vahna.net)
- #443: [Linux] fix a potential overflow issue for Process.set_cpu_affinity()
on systems with more than 64 CPUs.
- #448: [Windows] get_children() and ppid() memory leak (patch by Ulrich
Klank).
- #457: [POSIX] pid_exists() always returns True for PID 0.
- #461: namedtuples are not pickle-able.
- #466: [Linux] process exe improper null bytes handling. (patch by
Gautam Singh)
- #470: wait_procs() might not wait. (patch by crusaderky)
- #471: [Windows] process exe improper unicode handling. (patch by
alex@mroja.net)
- #473: psutil.Popen.wait() does not set returncode attribute.
- #474: [Windows] Process.cpu_percent() is no longer capped at 100%.
- #476: [Linux] encoding error for process name and cmdline.
**API changes**
For the sake of consistency a lot of psutil APIs have been renamed.
In most cases accessing the old names will work but it will cause a
DeprecationWarning.
- psutil.* module level constants have being replaced by functions:
+-----------------------+-------------------------------+
| Old name | Replacement |
+=======================+===============================+
| psutil.NUM_CPUS | psutil.cpu_cpunt() |
+-----------------------+-------------------------------+
| psutil.BOOT_TIME | psutil.boot_time() |
+-----------------------+-------------------------------+
| psutil.TOTAL_PHYMEM | psutil.virtual_memory().total |
+-----------------------+-------------------------------+
- Renamed psutil.* functions:
+--------------------------+-------------------------------+
| Old name | Replacement |
+==========================+===============================+
| - psutil.get_pid_list() | psutil.pids() |
+--------------------------+-------------------------------+
| - psutil.get_users() | psutil.users() |
+--------------------------+-------------------------------+
| - psutil.get_boot_time() | psutil.boot_time() |
+--------------------------+-------------------------------+
- All psutil.Process ``get_*`` methods lost the ``get_`` prefix.
get_ext_memory_info() renamed to memory_info_ex().
Assuming "p = psutil.Process()":
+--------------------------+----------------------+
| Old name | Replacement |
+==========================+======================+
| p.get_children() | p.children() |
+--------------------------+----------------------+
| p.get_connections() | p.connections() |
+--------------------------+----------------------+
| p.get_cpu_affinity() | p.cpu_affinity() |
+--------------------------+----------------------+
| p.get_cpu_percent() | p.cpu_percent() |
+--------------------------+----------------------+
| p.get_cpu_times() | p.cpu_times() |
+--------------------------+----------------------+
| p.get_ext_memory_info() | p.memory_info_ex() |
+--------------------------+----------------------+
| p.get_io_counters() | p.io_counters() |
+--------------------------+----------------------+
| p.get_ionice() | p.ionice() |
+--------------------------+----------------------+
| p.get_memory_info() | p.memory_info() |
+--------------------------+----------------------+
| p.get_memory_maps() | p.memory_maps() |
+--------------------------+----------------------+
| p.get_memory_percent() | p.memory_percent() |
+--------------------------+----------------------+
| p.get_nice() | p.nice() |
+--------------------------+----------------------+
| p.get_num_ctx_switches() | p.num_ctx_switches() |
+--------------------------+----------------------+
| p.get_num_fds() | p.num_fds() |
+--------------------------+----------------------+
| p.get_num_threads() | p.num_threads() |
+--------------------------+----------------------+
| p.get_open_files() | p.open_files() |
+--------------------------+----------------------+
| p.get_rlimit() | p.rlimit() |
+--------------------------+----------------------+
| p.get_threads() | p.threads() |
+--------------------------+----------------------+
| p.getcwd() | p.cwd() |
+--------------------------+----------------------+
- All psutil.Process ``set_*`` methods lost the ``set_`` prefix.
Assuming "p = psutil.Process()":
+----------------------+---------------------------------+
| Old name | Replacement |
+======================+=================================+
| p.set_nice() | p.nice(value) |
+----------------------+---------------------------------+
| p.set_ionice() | p.ionice(ioclass, value=None) |
+----------------------+---------------------------------+
| p.set_cpu_affinity() | p.cpu_affinity(cpus) |
+----------------------+---------------------------------+
| p.set_rlimit() | p.rlimit(resource, limits=None) |
+----------------------+---------------------------------+
- Except for 'pid' all psutil.Process class properties have been turned into
methods. This is the only case which there are no aliases.
Assuming "p = psutil.Process()":
+---------------+-----------------+
| Old name | Replacement |
+===============+=================+
| p.name | p.name() |
+---------------+-----------------+
| p.parent | p.parent() |
+---------------+-----------------+
| p.ppid | p.ppid() |
+---------------+-----------------+
| p.exe | p.exe() |
+---------------+-----------------+
| p.cmdline | p.cmdline() |
+---------------+-----------------+
| p.status | p.status() |
+---------------+-----------------+
| p.uids | p.uids() |
+---------------+-----------------+
| p.gids | p.gids() |
+---------------+-----------------+
| p.username | p.username() |
+---------------+-----------------+
| p.create_time | p.create_time() |
+---------------+-----------------+
- timeout parameter of cpu_percent* functions defaults to 0.0 instead of 0.1.
- long deprecated psutil.error module is gone; exception classes now live in
"psutil" namespace only.
- Process instances' "retcode" attribute returned by psutil.wait_procs() has
been renamed to "returncode" for consistency with subprocess.Popen.
1.2.1 - 2013-11-25
==================
**Bug fixes**
- #348: [Windows XP] fixed "ImportError: DLL load failed" occurring on module
import.
- #425: [Solaris] crash on import due to failure at determining BOOT_TIME.
- #443: [Linux] can't set CPU affinity on systems with more than 64 cores.
1.2.0 - 2013-11-20
==================
**Enhancements**
- #439: assume os.getpid() if no argument is passed to psutil.Process
constructor.
- #440: new psutil.wait_procs() utility function which waits for multiple
processes to terminate.
**Bug fixes**
- #348: [Windows XP/Vista] fix "ImportError: DLL load failed" occurring on
module import.
1.1.3 - 2013-11-07
==================
**Bug fixes**
- #442: [Linux] psutil won't compile on certain version of Linux because of
missing prlimit(2) syscall.
1.1.2 - 2013-10-22
==================
**Bug fixes**
- #442: [Linux] psutil won't compile on Debian 6.0 because of missing
prlimit(2) syscall.
1.1.1 - 2013-10-08
==================
**Bug fixes**
- #442: [Linux] psutil won't compile on kernels < 2.6.36 due to missing
prlimit(2) syscall.
1.1.0 - 2013-09-28
==================
**Enhancements**
- #410: host tar.gz and windows binary files are on PYPI.
- #412: [Linux] get/set process resource limits.
- #415: [Windows] Process.get_children() is an order of magnitude faster.
- #426: [Windows] Process.name is an order of magnitude faster.
- #431: [UNIX] Process.name is slightly faster because it unnecessarily
retrieved also process cmdline.
**Bug fixes**
- #391: [Windows] psutil.cpu_times_percent() returns negative percentages.
- #408: STATUS_* and CONN_* constants don't properly serialize on JSON.
- #411: [Windows] examples/disk_usage.py may pop-up a GUI error.
- #413: [Windows] Process.get_memory_info() leaks memory.
- #414: [Windows] Process.exe on Windows XP may raise ERROR_INVALID_PARAMETER.
- #416: psutil.disk_usage() doesn't work well with unicode path names.
- #430: [Linux] process IO counters report wrong number of r/w syscalls.
- #435: [Linux] psutil.net_io_counters() might report erreneous NIC names.
- #436: [Linux] psutil.net_io_counters() reports a wrong 'dropin' value.
**API changes**
- #408: turn STATUS_* and CONN_* constants into plain Python strings.
1.0.1 - 2013-07-12
==================
**Bug fixes**
- #405: network_io_counters(pernic=True) no longer works as intended in 1.0.0.
1.0.0 - 2013-07-10
==================
**Enhancements**
- #18: Solaris support (yay!) (thanks Justin Venus)
- #367: Process.get_connections() 'status' strings are now constants.
- #380: test suite exits with non-zero on failure. (patch by floppymaster)
- #391: introduce unittest2 facilities and provide workarounds if unittest2
is not installed (python < 2.7).
**Bug fixes**
- #374: [Windows] negative memory usage reported if process uses a lot of
memory.
- #379: [Linux] Process.get_memory_maps() may raise ValueError.
- #394: [OSX] Mapped memory regions report incorrect file name.
- #404: [Linux] sched_*affinity() are implicitly declared. (patch by Arfrever)
**API changes**
- Process.get_connections() 'status' field is no longer a string but a
constant object (psutil.CONN_*).
- Process.get_connections() 'local_address' and 'remote_address' fields
renamed to 'laddr' and 'raddr'.
- psutil.network_io_counters() renamed to psutil.net_io_counters().
0.7.1 - 2013-05-03
==================
**Bug fixes**
- #325: [BSD] psutil.virtual_memory() can raise SystemError.
(patch by Jan Beich)
- #370: [BSD] Process.get_connections() requires root. (patch by John Baldwin)
- #372: [BSD] different process methods raise NoSuchProcess instead of
AccessDenied.
0.7.0 - 2013-04-12
==================
**Enhancements**
- #233: code migrated to Mercurial (yay!)
- #246: psutil.error module is deprecated and scheduled for removal.
- #328: [Windows] process IO nice/priority support.
- #359: psutil.get_boot_time()
- #361: [Linux] psutil.cpu_times() now includes new 'steal', 'guest' and
'guest_nice' fields available on recent Linux kernels.
Also, psutil.cpu_percent() is more accurate.
- #362: cpu_times_percent() (per-CPU-time utilization as a percentage)
**Bug fixes**
- #234: [Windows] disk_io_counters() fails to list certain disks.
- #264: [Windows] use of psutil.disk_partitions() may cause a message box to
appear.
- #313: [Linux] psutil.virtual_memory() and psutil.swap_memory() can crash on
certain exotic Linux flavors having an incomplete /proc interface.
If that's the case we now set the unretrievable stats to 0 and raise a
RuntimeWarning.
- #315: [OSX] fix some compilation warnings.
- #317: [Windows] cannot set process CPU affinity above 31 cores.
- #319: [Linux] process get_memory_maps() raises KeyError 'Anonymous' on Debian
squeeze.
- #321: [UNIX] Process.ppid property is no longer cached as the kernel may set
the ppid to 1 in case of a zombie process.
- #323: [OSX] disk_io_counters()'s read_time and write_time parameters were
reporting microseconds not milliseconds. (patch by Gregory Szorc)
- #331: Process cmdline is no longer cached after first acces as it may change.
- #333: [OSX] Leak of Mach ports on OS X (patch by rsesek@google.com)
- #337: [Linux] process methods not working because of a poor /proc
implementation will raise NotImplementedError rather than RuntimeError
and Process.as_dict() will not blow up. (patch by Curtin1060)
- #338: [Linux] disk_io_counters() fails to find some disks.
- #339: [FreeBSD] get_pid_list() can allocate all the memory on system.
- #341: [Linux] psutil might crash on import due to error in retrieving system
terminals map.
- #344: [FreeBSD] swap_memory() might return incorrect results due to
kvm_open(3) not being called. (patch by Jean Sebastien)
- #338: [Linux] disk_io_counters() fails to find some disks.
- #351: [Windows] if psutil is compiled with mingw32 (provided installers for
py2.4 and py2.5 are) disk_io_counters() will fail. (Patch by m.malycha)
- #353: [OSX] get_users() returns an empty list on OSX 10.8.
- #356: Process.parent now checks whether parent PID has been reused in which
case returns None.
- #365: Process.set_nice() should check PID has not been reused by another
process.
- #366: [FreeBSD] get_memory_maps(), get_num_fds(), get_open_files() and
getcwd() Process methods raise RuntimeError instead of AccessDenied.
**API changes**
- Process.cmdline property is no longer cached after first access.
- Process.ppid property is no longer cached after first access.
- [Linux] Process methods not working because of a poor /proc implementation
will raise NotImplementedError instead of RuntimeError.
- psutil.error module is deprecated and scheduled for removal.
0.6.1 - 2012-08-16
==================
**Enhancements**
- #316: process cmdline property now makes a better job at guessing the process
executable from the cmdline.
**Bug fixes**
- #316: process exe was resolved in case it was a symlink.
- #318: python 2.4 compatibility was broken.
**API changes**
- process exe can now return an empty string instead of raising AccessDenied.
- process exe is no longer resolved in case it's a symlink.
0.6.0 - 2012-08-13
==================
**Enhancements**
- #216: [POSIX] get_connections() UNIX sockets support.
- #220: [FreeBSD] get_connections() has been rewritten in C and no longer
requires lsof.
- #222: [OSX] add support for process cwd.
- #261: process extended memory info.
- #295: [OSX] process executable path is now determined by asking the OS
instead of being guessed from process cmdline.
- #297: [OSX] the Process methods below were always raising AccessDenied for
any process except the current one. Now this is no longer true. Also
they are 2.5x faster.
- name
- get_memory_info()
- get_memory_percent()
- get_cpu_times()
- get_cpu_percent()
- get_num_threads()
- #300: examples/pmap.py script.
- #301: process_iter() now yields processes sorted by their PIDs.
- #302: process number of voluntary and involuntary context switches.
- #303: [Windows] the Process methods below were always raising AccessDenied
for any process not owned by current user. Now this is no longer true:
- create_time
- get_cpu_times()
- get_cpu_percent()
- get_memory_info()
- get_memory_percent()
- get_num_handles()
- get_io_counters()
- #305: add examples/netstat.py script.
- #311: system memory functions has been refactorized and rewritten and now
provide a more detailed and consistent representation of the system
memory. New psutil.virtual_memory() function provides the following
memory amounts:
- total
- available
- percent
- used
- active [POSIX]
- inactive [POSIX]
- buffers (BSD, Linux)
- cached (BSD, OSX)
- wired (OSX, BSD)
- shared [FreeBSD]
New psutil.swap_memory() provides:
- total
- used
- free
- percent
- sin (no. of bytes the system has swapped in from disk (cumulative))
- sout (no. of bytes the system has swapped out from disk (cumulative))
All old memory-related functions are deprecated.
Also two new example scripts were added: free.py and meminfo.py.
- #312: psutil.network_io_counters() namedtuple includes 4 new fields:
errin, errout dropin and dropout, reflecting the number of packets
dropped and with errors.
**Bugfixes**
- #298: [OSX and BSD] memory leak in get_num_fds().
- #299: potential memory leak every time PyList_New(0) is used.
- #303: [Windows] potential heap corruption in get_num_threads() and
get_status() Process methods.
- #305: [FreeBSD] psutil can't compile on FreeBSD 9 due to removal of utmp.h.
- #306: at C level, errors are not checked when invoking Py* functions which
create or manipulate Python objects leading to potential memory related
errors and/or segmentation faults.
- #307: [FreeBSD] values returned by psutil.network_io_counters() are wrong.
- #308: [BSD / Windows] psutil.virtmem_usage() wasn't actually returning
information about swap memory usage as it was supposed to do. It does
now.
- #309: get_open_files() might not return files which can not be accessed
due to limited permissions. AccessDenied is now raised instead.
**API changes**
- psutil.phymem_usage() is deprecated (use psutil.virtual_memory())
- psutil.virtmem_usage() is deprecated (use psutil.swap_memory())
- psutil.phymem_buffers() on Linux is deprecated (use psutil.virtual_memory())
- psutil.cached_phymem() on Linux is deprecated (use psutil.virtual_memory())
- [Windows and BSD] psutil.virtmem_usage() now returns information about swap
memory instead of virtual memory.
0.5.1 - 2012-06-29
==================
**Enhancements**
- #293: [Windows] process executable path is now determined by asking the OS
instead of being guessed from process cmdline.
**Bugfixes**
- #292: [Linux] race condition in process files/threads/connections.
- #294: [Windows] Process CPU affinity is only able to set CPU #0.
0.5.0 - 2012-06-27
==================
**Enhancements**
- #195: [Windows] number of handles opened by process.
- #209: psutil.disk_partitions() now provides also mount options.
- #229: list users currently connected on the system (psutil.get_users()).
- #238: [Linux, Windows] process CPU affinity (get and set).
- #242: Process.get_children(recursive=True): return all process
descendants.
- #245: [POSIX] Process.wait() incrementally consumes less CPU cycles.
- #257: [Windows] removed Windows 2000 support.
- #258: [Linux] Process.get_memory_info() is now 0.5x faster.
- #260: process's mapped memory regions. (Windows patch by wj32.64, OSX patch
by Jeremy Whitlock)
- #262: [Windows] psutil.disk_partitions() was slow due to inspecting the
floppy disk drive also when "all" argument was False.
- #273: psutil.get_process_list() is deprecated.
- #274: psutil no longer requires 2to3 at installation time in order to work
with Python 3.
- #278: new Process.as_dict() method.
- #281: ppid, name, exe, cmdline and create_time properties of Process class
are now cached after being accessed.
- #282: psutil.STATUS_* constants can now be compared by using their string
representation.
- #283: speedup Process.is_running() by caching its return value in case the
process is terminated.
- #284: [POSIX] per-process number of opened file descriptors.
- #287: psutil.process_iter() now caches Process instances between calls.
- #290: Process.nice property is deprecated in favor of new get_nice() and
set_nice() methods.
**Bugfixes**
- #193: psutil.Popen constructor can throw an exception if the spawned process
terminates quickly.
- #240: [OSX] incorrect use of free() for Process.get_connections().
- #244: [POSIX] Process.wait() can hog CPU resources if called against a
process which is not our children.
- #248: [Linux] psutil.network_io_counters() might return erroneous NIC names.
- #252: [Windows] process getcwd() erroneously raise NoSuchProcess for
processes owned by another user. It now raises AccessDenied instead.
- #266: [Windows] psutil.get_pid_list() only shows 1024 processes.
(patch by Amoser)
- #267: [OSX] Process.get_connections() - an erroneous remote address was
returned. (Patch by Amoser)
- #272: [Linux] Porcess.get_open_files() - potential race condition can lead to
unexpected NoSuchProcess exception. Also, we can get incorrect reports
of not absolutized path names.
- #275: [Linux] Process.get_io_counters() erroneously raise NoSuchProcess on
old Linux versions. Where not available it now raises
NotImplementedError.
- #286: Process.is_running() doesn't actually check whether PID has been
reused.
- #314: Process.get_children() can sometimes return non-children.
**API changes**
- Process.nice property is deprecated in favor of new get_nice() and set_nice()
methods.
- psutil.get_process_list() is deprecated.
- ppid, name, exe, cmdline and create_time properties of Process class are now
cached after being accessed, meaning NoSuchProcess will no longer be raised
in case the process is gone in the meantime.
- psutil.STATUS_* constants can now be compared by using their string
representation.
0.4.1 - 2011-12-14
==================
**Bugfixes**
- #228: some example scripts were not working with python 3.
- #230: [Windows / OSX] memory leak in Process.get_connections().
- #232: [Linux] psutil.phymem_usage() can report erroneous values which are
different than "free" command.
- #236: [Windows] memory/handle leak in Process's get_memory_info(),
suspend() and resume() methods.
0.4.0 - 2011-10-29
==================
**Enhancements**
- #150: network I/O counters. (OSX and Windows patch by Jeremy Whitlock)
- #154: [FreeBSD] add support for process getcwd()
- #157: [Windows] provide installer for Python 3.2 64-bit.
- #198: Process.wait(timeout=0) can now be used to make wait() return
immediately.
- #206: disk I/O counters. (OSX and Windows patch by Jeremy Whitlock)
- #213: examples/iotop.py script.
- #217: Process.get_connections() now has a "kind" argument to filter
for connections with different criteria.
- #221: [FreeBSD] Process.get_open_files has been rewritten in C and no longer
relies on lsof.
- #223: examples/top.py script.
- #227: examples/nettop.py script.
**Bugfixes**
- #135: [OSX] psutil cannot create Process object.
- #144: [Linux] no longer support 0 special PID.
- #188: [Linux] psutil import error on Linux ARM architectures.
- #194: [POSIX] psutil.Process.get_cpu_percent() now reports a percentage over
100 on multicore processors.
- #197: [Linux] Process.get_connections() is broken on platforms not
supporting IPv6.
- #200: [Linux] psutil.NUM_CPUS not working on armel and sparc architectures
and causing crash on module import.
- #201: [Linux] Process.get_connections() is broken on big-endian
architectures.
- #211: Process instance can unexpectedly raise NoSuchProcess if tested for
equality with another object.
- #218: [Linux] crash at import time on Debian 64-bit because of a missing
line in /proc/meminfo.
- #226: [FreeBSD] crash at import time on FreeBSD 7 and minor.
0.3.0 - 2011-07-08
==================
**Enhancements**
- #125: system per-cpu percentage utilization and times.
- #163: per-process associated terminal (TTY).
- #171: added get_phymem() and get_virtmem() functions returning system
memory information (total, used, free) and memory percent usage.
total_* avail_* and used_* memory functions are deprecated.
- #172: disk usage statistics.
- #174: mounted disk partitions.
- #179: setuptools is now used in setup.py
**Bugfixes**
- #159: SetSeDebug() does not close handles or unset impersonation on return.
- #164: [Windows] wait function raises a TimeoutException when a process
returns -1 .
- #165: process.status raises an unhandled exception.
- #166: get_memory_info() leaks handles hogging system resources.
- #168: psutil.cpu_percent() returns erroneous results when used in
non-blocking mode. (patch by Philip Roberts)
- #178: OSX - Process.get_threads() leaks memory
- #180: [Windows] Process's get_num_threads() and get_threads() methods can
raise NoSuchProcess exception while process still exists.
0.2.1 - 2011-03-20
==================
**Enhancements**
- #64: per-process I/O counters.
- #116: per-process wait() (wait for process to terminate and return its exit
code).
- #134: per-process get_threads() returning information (id, user and kernel
times) about threads opened by process.
- #136: process executable path on FreeBSD is now determined by asking the
kernel instead of guessing it from cmdline[0].
- #137: per-process real, effective and saved user and group ids.
- #140: system boot time.
- #142: per-process get and set niceness (priority).
- #143: per-process status.
- #147: per-process I/O nice (priority) - Linux only.
- #148: psutil.Popen class which tidies up subprocess.Popen and psutil.Process
in a unique interface.
- #152: [OSX] get_process_open_files() implementation has been rewritten
in C and no longer relies on lsof resulting in a 3x speedup.
- #153: [OSX] get_process_connection() implementation has been rewritten
in C and no longer relies on lsof resulting in a 3x speedup.
**Bugfixes**
- #83: process cmdline is empty on OSX 64-bit.
- #130: a race condition can cause IOError exception be raised on
Linux if process disappears between open() and subsequent read() calls.
- #145: WindowsError was raised instead of psutil.AccessDenied when using
process resume() or suspend() on Windows.
- #146: 'exe' property on Linux can raise TypeError if path contains NULL
bytes.
- #151: exe and getcwd() for PID 0 on Linux return inconsistent data.
**API changes**
- Process "uid" and "gid" properties are deprecated in favor of "uids" and
"gids" properties.
0.2.0 - 2010-11-13
==================
**Enhancements**
- #79: per-process open files.
- #88: total system physical cached memory.
- #88: total system physical memory buffers used by the kernel.
- #91: per-process send_signal() and terminate() methods.
- #95: NoSuchProcess and AccessDenied exception classes now provide "pid",
"name" and "msg" attributes.
- #97: per-process children.
- #98: Process.get_cpu_times() and Process.get_memory_info now return
a namedtuple instead of a tuple.
- #103: per-process opened TCP and UDP connections.
- #107: add support for Windows 64 bit. (patch by cjgohlke)
- #111: per-process executable name.
- #113: exception messages now include process name and pid.
- #114: process username Windows implementation has been rewritten in pure
C and no longer uses WMI resulting in a big speedup. Also, pywin32 is no
longer required as a third-party dependancy. (patch by wj32)
- #117: added support for Windows 2000.
- #123: psutil.cpu_percent() and psutil.Process.cpu_percent() accept a
new 'interval' parameter.
- #129: per-process number of threads.
**Bugfixes**
- #80: fixed warnings when installing psutil with easy_install.
- #81: psutil fails to compile with Visual Studio.
- #94: suspend() raises OSError instead of AccessDenied.
- #86: psutil didn't compile against FreeBSD 6.x.
- #102: orphaned process handles obtained by using OpenProcess in C were
left behind every time Process class was instantiated.
- #111: path and name Process properties report truncated or erroneous
values on UNIX.
- #120: cpu_percent() always returning 100% on OS X.
- #112: uid and gid properties don't change if process changes effective
user/group id at some point.
- #126: ppid, uid, gid, name, exe, cmdline and create_time properties are
no longer cached and correctly raise NoSuchProcess exception if the process
disappears.
**API changes**
- psutil.Process.path property is deprecated and works as an alias for "exe"
property.
- psutil.Process.kill(): signal argument was removed - to send a signal to the
process use send_signal(signal) method instead.
- psutil.Process.get_memory_info() returns a nametuple instead of a tuple.
- psutil.cpu_times() returns a nametuple instead of a tuple.
- New psutil.Process methods: get_open_files(), get_connections(),
send_signal() and terminate().
- ppid, uid, gid, name, exe, cmdline and create_time properties are no longer
cached and raise NoSuchProcess exception if process disappears.
- psutil.cpu_percent() no longer returns immediately (see issue 123).
- psutil.Process.get_cpu_percent() and psutil.cpu_percent() no longer returns
immediately by default (see issue 123).
0.1.3 - 2010-03-02
==================
**Enhancements**
- #14: per-process username
- #51: per-process current working directory (Windows and Linux only)
- #59: Process.is_running() is now 10 times faster
- #61: added supoprt for FreeBSD 64 bit
- #71: implemented suspend/resume process
- #75: python 3 support
**Bugfixes**
- #36: process cpu_times() and memory_info() functions succeeded also for dead
processes while a NoSuchProcess exception is supposed to be raised.
- #48: incorrect size for mib array defined in getcmdargs for BSD
- #49: possible memory leak due to missing free() on error condition on
- #50: fixed getcmdargs() memory fragmentation on BSD
- #55: test_pid_4 was failing on Windows Vista
- #57: some unit tests were failing on systems where no swap memory is
available
- #58: is_running() is now called before kill() to make sure we are going
to kill the correct process.
- #73: virtual memory size reported on OS X includes shared library size
- #77: NoSuchProcess wasn't raised on Process.create_time if kill() was
used first.
0.1.2 - 2009-05-06
==================
**Enhancements**
- #32: Per-process CPU user/kernel times
- #33: Process create time
- #34: Per-process CPU utilization percentage
- #38: Per-process memory usage (bytes)
- #41: Per-process memory utilization (percent)
- #39: System uptime
- #43: Total system virtual memory
- #46: Total system physical memory
- #44: Total system used/free virtual and physical memory
**Bugfixes**
- #36: [Windows] NoSuchProcess not raised when accessing timing methods.
- #40: test_get_cpu_times() failing on FreeBSD and OS X.
- #42: [Windows] get_memory_percent() raises AccessDenied.
0.1.1 - 2009-03-06
==================
**Enhancements**
- #4: FreeBSD support for all functions of psutil
- #9: Process.uid and Process.gid now retrieve process UID and GID.
- #11: Support for parent/ppid - Process.parent property returns a
Process object representing the parent process, and Process.ppid returns
the parent PID.
- #12 & 15:
NoSuchProcess exception now raised when creating an object
for a nonexistent process, or when retrieving information about a process
that has gone away.
- #21: AccessDenied exception created for raising access denied errors
from OSError or WindowsError on individual platforms.
- #26: psutil.process_iter() function to iterate over processes as
Process objects with a generator.
- #?: Process objects can now also be compared with == operator for equality
(PID, name, command line are compared).
**Bugfixes**
- #16: [Windows] Special case for "System Idle Process" (PID 0) which
otherwise would return an "invalid parameter" exception.
- #17: get_process_list() ignores NoSuchProcess and AccessDenied
exceptions during building of the list.
- #22: [Windows] Process(0).kill() was failing with an unset exception.
- #23: Special case for pid_exists(0)
- #24: [Windows] Process(0).kill() now raises AccessDenied exception instead
of WindowsError.
- #30: psutil.get_pid_list() was returning two instances of PID 0 on OSX and
FreeBSD platforms.
0.1.0 - 2009-01-27
==================
- Initial release.

144
python/psutil/INSTALL.rst Normal file
View File

@ -0,0 +1,144 @@
============================
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:
$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
python ez_setup.py
...then run:
$ pip install psutil
You may need to install gcc and python header files first (see later).
=====================
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.
========================================
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::
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
...then run:
setup.py build
...or:
make.bat build
Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires
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:
$ sudo apt-get install gcc python-dev
...on Redhat and CentOS:
$ sudo yum install gcc python-devel
Once done, you can build/install psutil with:
$ python setup.py install
==================
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:
$ python setup.py build
To install and build:
$ python setup.py install
=====================
Installing on FreeBSD
=====================
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:
$ python setup.py build
Install and build:
$ python setup.py install
========
Makefile
========
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 uninstall # uninstall (needs pip)
$ make test # run tests
$ make clean # remove installation files

View File

@ -1,10 +1,17 @@
include .travis.yml
include CREDITS
include HISTORY
include HISTORY.rst
include INSTALL.rst
include LICENSE
include make.bat
include Makefile
include MANIFEST.in
include README
include TODO
include README.rst
include setup.py
recursive-include psutil *.py *.c *.h
recursive-include test *.py
include TODO
include tox.ini
recursive-include docs *
recursive-exclude docs/_build *
recursive-include examples *.py
recursive-include psutil *.py *.c *.h
recursive-include test *.py README

90
python/psutil/Makefile Normal file
View File

@ -0,0 +1,90 @@
# Shortcuts for various tasks (UNIX only).
# To use a specific Python version run:
# $ make install PYTHON=python3.3
# You can set these variables from the command line.
PYTHON = python
TSCRIPT = test/test_psutil.py
all: test
clean:
rm -f `find . -type f -name \*.py[co]`
rm -f `find . -type f -name \*.so`
rm -f `find . -type f -name .\*~`
rm -f `find . -type f -name \*.orig`
rm -f `find . -type f -name \*.bak`
rm -f `find . -type f -name \*.rej`
rm -rf `find . -type d -name __pycache__`
rm -rf *.egg-info
rm -rf *\$testfile*
rm -rf .tox
rm -rf build
rm -rf dist
rm -rf docs/_build
build: clean
$(PYTHON) setup.py build
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
uninstall:
if test $(PYTHON) = python2.4; then \
pip-2.4 uninstall -y -v psutil; \
else \
cd ..; $(PYTHON) -m pip uninstall -y -v psutil; \
fi
test: install
$(PYTHON) $(TSCRIPT)
test-process: install
$(PYTHON) -m unittest -v test.test_psutil.TestProcess
test-system: install
$(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs
test-memleaks: install
$(PYTHON) -m unittest -v test.test_memory_leaks
# 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))
# requires "pip install pep8"
pep8:
@git ls-files | grep \\.py$ | xargs pep8
# requires "pip install pyflakes"
pyflakes:
@export PYFLAKES_NODOCTEST=1 && \
git ls-files | grep \\.py$ | xargs pyflakes
# requires "pip install flake8"
flake8:
@git ls-files | grep \\.py$ | xargs flake8
# Upload source tarball on https://pypi.python.org/pypi/psutil.
upload-src: clean
$(PYTHON) setup.py sdist upload
# Build and upload doc on https://pythonhosted.org/psutil/.
# Requires "pip install sphinx-pypi-upload".
upload-doc:
cd docs; make html
$(PYTHON) setup.py upload_sphinx --upload-dir=docs/_build/html
# git-tag a new release
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"

View File

@ -1,33 +1,74 @@
Metadata-Version: 1.1
Name: psutil
Version: 1.0.1
Summary: A process and system utilities module for Python
Home-page: http://code.google.com/p/psutil/
Version: 2.1.3
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: License :: OSI Approved :: BSD License
Download-URL: http://psutil.googlecode.com/files/psutil-1.0.1.tar.gz
Description: ===========
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
.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master
:target: https://travis-ci.org/giampaolo/psutil
:alt: Travis
===========
Quick links
===========
* `Home page <http://code.google.com/p/psutil>`_
* `Download <http://code.google.com/p/psutil/downloads/list>`_
* `Documentation <http://code.google.com/p/psutil/wiki/Documentation>`_
- `Home page <https://github.com/giampaolo/psutil>`_
- `Documentation <http://pythonhosted.org/psutil/>`_
- `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>`_
- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_
=======
Summary
=======
psutil is a module providing an interface for retrieving information on all
running processes and system utilization (CPU, memory, disks, network, users) in
a portable way by using Python, implementing many functionalities offered by
command line tools such as: **ps, top, df, kill, free, lsof, free, netstat,
ifconfig, nice, ionice, iostat, iotop, uptime, pidof, tty, who, taskset, pmap**.
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.4 to 3.4**. PyPy is
also known to work.
It currently supports **Linux**, **Windows**, **OSX**, **FreeBSD**,
**Sun Solaris** both **32-bit** and **64-bit** with Python versions from **2.4**
to **3.3** by using a single code base.
====================
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/Jahaja/psdash
* https://code.google.com/p/grr/
==============
Example usages
@ -36,209 +77,303 @@ Description: ===========
CPU
===
>>> import psutil
>>> psutil.cpu_times()
cputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540,
iowait=629.509, irq=0.0, softirq=19.422, 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]
[7.0, 8.5]
[1.2, 9.0]
>>>
>>> for x in range(3):
... psutil.cpu_times_percent(interval=1, percpu=False)
...
cpupercent(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)
cpupercent(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)
cpupercent(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)
.. 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
======
>>> psutil.virtual_memory()
vmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L,
free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L,
cached=1251086336)
>>> psutil.swap_memory()
swap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1,
sin=304193536, sout=677842944)
>>>
.. 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)
>>> psutil.swap_memory()
sswap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1, sin=304193536, sout=677842944)
>>>
Disks
=====
>>> psutil.disk_partitions()
[partition(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
partition(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
>>>
>>> psutil.disk_usage('/')
usage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
>>>
>>> psutil.disk_io_counters()
iostat(read_count=719566, write_count=1082197, read_bytes=18626220032,
write_bytes=24081764352, read_time=5023392, write_time=63199568)
>>>
.. 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
=======
>>> psutil.net_io_counters(pernic=True)
{'lo': iostat(bytes_sent=799953745, bytes_recv=799953745,
packets_sent=453698, packets_recv=453698),
'eth0': iostat(bytes_sent=734324837, bytes_recv=4163935363,
packets_sent=3605828, packets_recv=4096685)}
>>>
.. 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=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)
...]
Other system info
=================
>>> psutil.get_users()
[user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
>>>
>>> psutil.get_boot_time()
1365519115.0
.. 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
==================
>>> import psutil
>>> psutil.get_pid_list()
[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.getcwd()
'/home/giampaolo'
>>> p.cmdline
['/usr/bin/python', 'main.py']
>>>
>>> str(p.status)
'running'
>>> p.username
'giampaolo'
>>> p.create_time
1267551141.5019531
>>> p.terminal
'/dev/pts/0'
>>>
>>> p.uids
user(real=1000, effective=1000, saved=1000)
>>> p.gids
group(real=1000, effective=1000, saved=1000)
>>>
>>> p.get_cpu_times()
cputimes(user=1.02, system=0.31)
>>> p.get_cpu_percent(interval=1.0)
12.1
>>> p.get_cpu_affinity()
[0, 1, 2, 3]
>>> p.set_cpu_affinity([0])
>>>
>>> p.get_memory_percent()
0.63423
>>>
>>> p.get_memory_info()
meminfo(rss=7471104, vms=68513792)
>>> p.get_ext_memory_info()
meminfo(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
>>> p.get_memory_maps()
[mmap(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
mmap(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
mmap(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
mmap(path='[heap]', rss=54653, anonymous=8192, swap=0),
mmap(path='[stack]', rss=1542, anonymous=166, swap=0),
...]
>>>
>>> p.get_io_counters()
io(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
>>>
>>> p.get_open_files()
[openfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
>>>
>>> p.get_connections()
[connection(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776),
raddr=('93.186.135.91', 80), status='ESTABLISHED'),
connection(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761),
raddr=('72.14.234.100', 80), status='CLOSING'),
connection(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759),
raddr=('72.14.234.104', 80), status='ESTABLISHED'),
connection(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314),
raddr=('72.14.234.83', 443), status='SYN_SENT')]
>>>
>>> p.get_num_threads()
4
>>> p.get_num_fds()
8
>>> p.get_threads()
[thread(id=5234, user_time=22.5, system_time=9.2891),
thread(id=5235, user_time=0.0, system_time=0.0),
thread(id=5236, user_time=0.0, system_time=0.0),
thread(id=5237, user_time=0.0707, system_time=1.1)]
>>>
>>> p.get_num_ctx_switches()
amount(voluntary=78, involuntary=19)
>>>
>>> p.get_nice()
0
>>> p.set_nice(10)
>>>
>>> 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
>>>
.. code-block:: python
Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,monitoring
>>> 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.ext_memory_info()
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=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')]
>>>
>>> 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=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
========
- 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,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
Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: POSIX :: BSD :: FreeBSD
Classifier: Operating System :: POSIX :: SunOS/Solaris
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
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.4
Classifier: Programming Language :: Python :: 2.5
@ -249,15 +384,16 @@ 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: Topic :: System :: Monitoring
Classifier: Topic :: System :: Networking
Classifier: Topic :: System :: Networking :: Monitoring
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
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: BSD License

View File

@ -1,217 +0,0 @@
===========
Quick links
===========
* `Home page <http://code.google.com/p/psutil>`_
* `Download <http://code.google.com/p/psutil/downloads/list>`_
* `Documentation <http://code.google.com/p/psutil/wiki/Documentation>`_
=======
Summary
=======
psutil is a module providing an interface for retrieving information on all
running processes and system utilization (CPU, memory, disks, network, users) in
a portable way by using Python, implementing many functionalities offered by
command line tools such as: **ps, top, df, kill, free, lsof, free, netstat,
ifconfig, nice, ionice, iostat, iotop, uptime, pidof, tty, who, taskset, pmap**.
It currently supports **Linux**, **Windows**, **OSX**, **FreeBSD**,
**Sun Solaris** both **32-bit** and **64-bit** with Python versions from **2.4**
to **3.3** by using a single code base.
==============
Example usages
==============
CPU
===
>>> import psutil
>>> psutil.cpu_times()
cputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540,
iowait=629.509, irq=0.0, softirq=19.422, 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]
[7.0, 8.5]
[1.2, 9.0]
>>>
>>> for x in range(3):
... psutil.cpu_times_percent(interval=1, percpu=False)
...
cpupercent(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)
cpupercent(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)
cpupercent(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)
Memory
======
>>> psutil.virtual_memory()
vmem(total=8374149120L, available=2081050624L, percent=75.1, used=8074080256L,
free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L,
cached=1251086336)
>>> psutil.swap_memory()
swap(total=2097147904L, used=296128512L, free=1801019392L, percent=14.1,
sin=304193536, sout=677842944)
>>>
Disks
=====
>>> psutil.disk_partitions()
[partition(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
partition(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
>>>
>>> psutil.disk_usage('/')
usage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
>>>
>>> psutil.disk_io_counters()
iostat(read_count=719566, write_count=1082197, read_bytes=18626220032,
write_bytes=24081764352, read_time=5023392, write_time=63199568)
>>>
Network
=======
>>> psutil.net_io_counters(pernic=True)
{'lo': iostat(bytes_sent=799953745, bytes_recv=799953745,
packets_sent=453698, packets_recv=453698),
'eth0': iostat(bytes_sent=734324837, bytes_recv=4163935363,
packets_sent=3605828, packets_recv=4096685)}
>>>
Other system info
=================
>>> psutil.get_users()
[user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0),
user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)]
>>>
>>> psutil.get_boot_time()
1365519115.0
Process management
==================
>>> import psutil
>>> psutil.get_pid_list()
[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.getcwd()
'/home/giampaolo'
>>> p.cmdline
['/usr/bin/python', 'main.py']
>>>
>>> str(p.status)
'running'
>>> p.username
'giampaolo'
>>> p.create_time
1267551141.5019531
>>> p.terminal
'/dev/pts/0'
>>>
>>> p.uids
user(real=1000, effective=1000, saved=1000)
>>> p.gids
group(real=1000, effective=1000, saved=1000)
>>>
>>> p.get_cpu_times()
cputimes(user=1.02, system=0.31)
>>> p.get_cpu_percent(interval=1.0)
12.1
>>> p.get_cpu_affinity()
[0, 1, 2, 3]
>>> p.set_cpu_affinity([0])
>>>
>>> p.get_memory_percent()
0.63423
>>>
>>> p.get_memory_info()
meminfo(rss=7471104, vms=68513792)
>>> p.get_ext_memory_info()
meminfo(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0)
>>> p.get_memory_maps()
[mmap(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0),
mmap(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0),
mmap(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0),
mmap(path='[heap]', rss=54653, anonymous=8192, swap=0),
mmap(path='[stack]', rss=1542, anonymous=166, swap=0),
...]
>>>
>>> p.get_io_counters()
io(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632)
>>>
>>> p.get_open_files()
[openfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)]
>>>
>>> p.get_connections()
[connection(fd=115, family=2, type=1, laddr=('10.0.0.1', 48776),
raddr=('93.186.135.91', 80), status='ESTABLISHED'),
connection(fd=117, family=2, type=1, laddr=('10.0.0.1', 43761),
raddr=('72.14.234.100', 80), status='CLOSING'),
connection(fd=119, family=2, type=1, laddr=('10.0.0.1', 60759),
raddr=('72.14.234.104', 80), status='ESTABLISHED'),
connection(fd=123, family=2, type=1, laddr=('10.0.0.1', 51314),
raddr=('72.14.234.83', 443), status='SYN_SENT')]
>>>
>>> p.get_num_threads()
4
>>> p.get_num_fds()
8
>>> p.get_threads()
[thread(id=5234, user_time=22.5, system_time=9.2891),
thread(id=5235, user_time=0.0, system_time=0.0),
thread(id=5236, user_time=0.0, system_time=0.0),
thread(id=5237, user_time=0.0707, system_time=1.1)]
>>>
>>> p.get_num_ctx_switches()
amount(voluntary=78, involuntary=19)
>>>
>>> p.get_nice()
0
>>> p.set_nice(10)
>>>
>>> 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
>>>

349
python/psutil/README.rst Normal file
View File

@ -0,0 +1,349 @@
.. 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://api.travis-ci.org/giampaolo/psutil.png?branch=master
:target: https://travis-ci.org/giampaolo/psutil
:alt: Travis
===========
Quick links
===========
- `Home page <https://github.com/giampaolo/psutil>`_
- `Documentation <http://pythonhosted.org/psutil/>`_
- `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>`_
- `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.4 to 3.4**. PyPy 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/Jahaja/psdash
* https://code.google.com/p/grr/
==============
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=8374149120L, available=2081050624L, percent=75.1, used=8074080256L, free=300068864L, active=3294920704, inactive=1361616896, buffers=529895424L, cached=1251086336)
>>> psutil.swap_memory()
sswap(total=2097147904L, used=296128512L, free=1801019392L, 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=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)
...]
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.ext_memory_info()
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=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')]
>>>
>>> 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=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
========
- 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>`_

View File

@ -3,29 +3,28 @@ TODO
A collection of ideas and notes about stuff to implement in future versions.
"#NNN" occurrences refer to bug tracker issues at:
https://code.google.com/p/psutil/issues/list
https://github.com/giampaolo/psutil/issues
HIGHER PRIORITY
===============
* #387: system-wide connections (netstat).
* #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).
* #250: net ifaces speed.
* (Linux) resource limit get/set - see man prlimit.
* Process.name on Windows is slow:
http://stackoverflow.com/questions/6587036/
* Windows binary for Python 3.3 64-bit.
* #269: expose network ifaces RX/TW queues.
* Process.threads(): thread names
* Asynchronous psutil.Popen (see http://bugs.python.org/issue1191964)
LOWER PRIORITY
==============
@ -34,20 +33,20 @@ LOWER PRIORITY
* #276: GNU/Hurd support.
* NetBSD support?
* #429: NetBSD support.
* DranflyBSD support?
* DragonFlyBSD support?
* AIX support?
* examples/pidof.py (same as 'pidof' cli tool)
* examples/pstree.py (same as 'pstree' cli tool)
* get_threads() should also return thread names in order to implement it
* threads() should also return thread names in order to implement it
* examples/taskmgr-gui.py (using tk).
* system-wide # open file descriptors:
* system-wide number of open file descriptors:
* https://jira.hyperic.com/browse/SIGAR-30
* http://www.netadmintools.com/part295.html
@ -59,26 +58,28 @@ LOWER PRIORITY
* thread names:
* https://code.google.com/p/plcrashreporter/issues/detail?id=65
* 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()
killall-> (actual script)
tty -> psutil.Process.terminal()
who -> psutil.users()
DEBATABLE
=========
* support wheels? http://pythonwheels.com/
* advanced cmdline interface exposing the whole API and providing different
kind of outputs (e.g. pprinted, colorized, json).
* [Linux]: process cgroups (http://en.wikipedia.org/wiki/Cgroups). They look
similar to prlimit() in terms of functionality but uglier (they should allow
limiting per-process network IO resources though, which is great). Needs
further reading.
* cpu_percent(): current default interval is 0.1 so that by default it will
produce a meaningful value. It represents a trap in case the user iterates
over multiple processes though, as it introduces a big slowdown.
Should it default to 0.0?
* Rename connection ntuple's fields 'local_address', 'remote_address' to
'laddr', 'raddr' (note in accordance with http://bugs.python.org/issue17675)
* Process per-cpus percent (XXX Windows only?), see:
https://groups.google.com/forum/?fromgroups#!topic/psutil/ErrKTxAbu50
* Should we expose OS constants (psutil.WINDOWS, psutil.OSX etc.)?
* Python 3.3. exposed different sched.h functions:
@ -91,5 +92,59 @@ DEBATABLE
implemented as a busy-loop.
* Certain systems (XXX figure out which ones exactly) provide CPU times about
process children. On those systems Process.get_cpu_times() might return
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.
* Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that:
- NoSuchProcess inherits from ProcessLookupError
- AccessDenied inherits from PermissionError
- TimeoutExpired inherits from TimeoutError (debatable)
See: http://docs.python.org/3/library/exceptions.html#os-exceptions
* Process.threads() might grow an extra "id" parameter so that it can be
used as such:
>>> p = psutil.Process(os.getpid())
>>> p.threads(id=psutil.current_thread_id())
thread(id=2539, user_time=0.03, system_time=0.02)
>>>
Note: this leads to questions such as "should we have a custom NoSuchThread
exception? Also see issue #418.
Note #2: this would work with os.getpid() only.
psutil.current_thread_id() might be desirable as per issue #418 though.
* should psutil.TimeoutExpired exception have a 'msg' kwarg similar to
NoSuchProcess and AccessDenied? Not that we need it, but currently we
cannot raise a TimeoutExpired exception with a specific error string.
* process_iter() might grow an "attrs" parameter similar to Process.as_dict()
invoke the necessary methods and include the results into a "cache"
attribute attached to the returned Process instances so that one can avoid
catching NSP and AccessDenied:
for p in process_iter(attrs=['cpu_percent']):
print(p.cache['cpu_percent'])
This also leads questions as whether we should introduce a sorting order.
* round Process.memory_percent() result?
COMPATIBILITY BREAKAGE
======================
Removals (will likely happen in 2.2):
* (S) psutil.Process.nice (deprecated in 0.5.0)
* (S) get_process_list (deprecated in 0.5.0)
* (S) psutil.*mem* functions (deprecated in 0.3.0 and 0.6.0)
* (M) psutil.network_io_counters (deprecated in 1.0.0)
* (M) local_address and remote_address Process.connection() namedtuple fields
(deprecated in 1.0.0)
REJECTED IDEAS
==============
STUB

177
python/psutil/docs/Makefile Normal file
View File

@ -0,0 +1,177 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psutil.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psutil.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/psutil"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/psutil"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

15
python/psutil/docs/README Normal file
View File

@ -0,0 +1,15 @@
About
=====
This directory contains the reStructuredText (reST) sources to the psutil
documentation. You don't need to build them yourself, prebuilt versions are
available at https://pythonhosted.org/psutil/.
In case you want, you need to install sphinx first:
$ pip install sphinx
Then run:
$ make html
You'll then have an HTML version of the doc at _build/html/index.html.

View File

@ -0,0 +1,57 @@
$(document).ready(function() {
/* Add a [>>>] button on the top-right corner of code samples to hide
* the >>> and ... prompts and the output and thus make the code
* copyable. */
var div = $('.highlight-python .highlight,' +
'.highlight-python3 .highlight')
var pre = div.find('pre');
// get the styles from the current theme
pre.parent().parent().css('position', 'relative');
var hide_text = 'Hide the prompts and output';
var show_text = 'Show the prompts and output';
var border_width = pre.css('border-top-width');
var border_style = pre.css('border-top-style');
var border_color = pre.css('border-top-color');
var button_styles = {
'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
'border-color': border_color, 'border-style': border_style,
'border-width': border_width, 'color': border_color, 'text-size': '75%',
'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
'border-radius': '0 3px 0 0'
}
// create and add the button to all the code blocks that contain >>>
div.each(function(index) {
var jthis = $(this);
if (jthis.find('.gp').length > 0) {
var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
button.css(button_styles)
button.attr('title', hide_text);
jthis.prepend(button);
}
// tracebacks (.gt) contain bare text elements that need to be
// wrapped in a span to work with .nextUntil() (see later)
jthis.find('pre:has(.gt)').contents().filter(function() {
return ((this.nodeType == 3) && (this.data.trim().length > 0));
}).wrap('<span>');
});
// define the behavior of the button when it's clicked
$('.copybutton').toggle(
function() {
var button = $(this);
button.parent().find('.go, .gp, .gt').hide();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
button.css('text-decoration', 'line-through');
button.attr('title', show_text);
},
function() {
var button = $(this);
button.parent().find('.go, .gp, .gt').show();
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
button.css('text-decoration', 'none');
button.attr('title', hide_text);
});
});

BIN
python/psutil/docs/_static/favicon.ico vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
python/psutil/docs/_static/logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

161
python/psutil/docs/_static/sidebar.js vendored Normal file
View File

@ -0,0 +1,161 @@
/*
* sidebar.js
* ~~~~~~~~~~
*
* This script makes the Sphinx sidebar collapsible.
*
* .sphinxsidebar contains .sphinxsidebarwrapper. This script adds in
* .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to
* collapse and expand the sidebar.
*
* When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the
* width of the sidebar and the margin-left of the document are decreased.
* When the sidebar is expanded the opposite happens. This script saves a
* per-browser/per-session cookie used to remember the position of the sidebar
* among the pages. Once the browser is closed the cookie is deleted and the
* position reset to the default (expanded).
*
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
$(function() {
// global elements used by the functions.
// the 'sidebarbutton' element is defined as global after its
// creation, in the add_sidebar_button function
var bodywrapper = $('.bodywrapper');
var sidebar = $('.sphinxsidebar');
var sidebarwrapper = $('.sphinxsidebarwrapper');
// original margin-left of the bodywrapper and width of the sidebar
// with the sidebar expanded
var bw_margin_expanded = bodywrapper.css('margin-left');
var ssb_width_expanded = sidebar.width();
// margin-left of the bodywrapper and width of the sidebar
// with the sidebar collapsed
var bw_margin_collapsed = '.8em';
var ssb_width_collapsed = '.8em';
// colors used by the current theme
var dark_color = '#AAAAAA';
var light_color = '#CCCCCC';
function sidebar_is_collapsed() {
return sidebarwrapper.is(':not(:visible)');
}
function toggle_sidebar() {
if (sidebar_is_collapsed())
expand_sidebar();
else
collapse_sidebar();
}
function collapse_sidebar() {
sidebarwrapper.hide();
sidebar.css('width', ssb_width_collapsed);
bodywrapper.css('margin-left', bw_margin_collapsed);
sidebarbutton.css({
'margin-left': '0',
//'height': bodywrapper.height(),
'height': sidebar.height(),
'border-radius': '5px'
});
sidebarbutton.find('span').text('»');
sidebarbutton.attr('title', _('Expand sidebar'));
document.cookie = 'sidebar=collapsed';
}
function expand_sidebar() {
bodywrapper.css('margin-left', bw_margin_expanded);
sidebar.css('width', ssb_width_expanded);
sidebarwrapper.show();
sidebarbutton.css({
'margin-left': ssb_width_expanded-12,
//'height': bodywrapper.height(),
'height': sidebar.height(),
'border-radius': '0 5px 5px 0'
});
sidebarbutton.find('span').text('«');
sidebarbutton.attr('title', _('Collapse sidebar'));
//sidebarwrapper.css({'padding-top':
// Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)});
document.cookie = 'sidebar=expanded';
}
function add_sidebar_button() {
sidebarwrapper.css({
'float': 'left',
'margin-right': '0',
'width': ssb_width_expanded - 28
});
// create the button
sidebar.append(
'<div id="sidebarbutton"><span>&laquo;</span></div>'
);
var sidebarbutton = $('#sidebarbutton');
// find the height of the viewport to center the '<<' in the page
var viewport_height;
if (window.innerHeight)
viewport_height = window.innerHeight;
else
viewport_height = $(window).height();
var sidebar_offset = sidebar.offset().top;
var sidebar_height = sidebar.height();
//var sidebar_height = Math.max(bodywrapper.height(), sidebar.height());
sidebarbutton.find('span').css({
'display': 'block',
'margin-top': sidebar_height/2 - 10
//'margin-top': (viewport_height - sidebar.position().top - 20) / 2
//'position': 'fixed',
//'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10
});
sidebarbutton.click(toggle_sidebar);
sidebarbutton.attr('title', _('Collapse sidebar'));
sidebarbutton.css({
'border-radius': '0 5px 5px 0',
'color': '#444444',
'background-color': '#CCCCCC',
'font-size': '1.2em',
'cursor': 'pointer',
'height': sidebar_height,
'padding-top': '1px',
'padding-left': '1px',
'margin-left': ssb_width_expanded - 12
});
sidebarbutton.hover(
function () {
$(this).css('background-color', dark_color);
},
function () {
$(this).css('background-color', light_color);
}
);
}
function set_position_from_cookie() {
if (!document.cookie)
return;
var items = document.cookie.split(';');
for(var k=0; k<items.length; k++) {
var key_val = items[k].split('=');
var key = key_val[0];
if (key == 'sidebar') {
var value = key_val[1];
if ((value == 'collapsed') && (!sidebar_is_collapsed()))
collapse_sidebar();
else if ((value == 'expanded') && (sidebar_is_collapsed()))
expand_sidebar();
}
}
}
add_sidebar_button();
var sidebarbutton = $('#sidebarbutton');
set_position_from_cookie();
});

View File

@ -0,0 +1,12 @@
{#
basic/globaltoc.html
~~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: global table of contents.
:copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
<h3>{{ _('Manual') }}</h3>
{{ toctree() }}
<a href="{{ pathto(master_doc) }}">Back to Welcome</a>

View File

@ -0,0 +1,4 @@
{% extends "defindex.html" %}
{% block tables %}
{% endblock %}

View File

@ -0,0 +1,8 @@
<h3>Useful links</h3>
<ul>
<li><a href="https://github.com/giampaolo/psutil">Github project</a></li>
<li><a href="http://grodola.blogspot.com/search/label/psutil">Blog</a></li>
<li><a href="https://pypi.python.org/pypi?:action=display&name=psutil#downloads">Download</a></li>
<li><a href="https://github.com/giampaolo/psutil/issues">Issues</a></li>
<li><a href="http://groups.google.com/group/psutil/topics">Forum</a></li>
</ul>

66
python/psutil/docs/_template/page.html vendored Normal file
View File

@ -0,0 +1,66 @@
{% extends "!page.html" %}
{% block extrahead %}
{{ super() }}
{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %}
<script type="text/javascript">
// Store editor pop-up help state in localStorage
// so it does not re-pop-up itself between page loads.
// Do not even to pretend to support IE gracefully.
(function($) {
$(document).ready(function() {
var box = $("#editor-trap");
var klass = "toggled";
var storageKey = "toggled";
function toggle() {
box.toggleClass(klass);
// Store the toggle status in local storage as "has value string" or null
window.localStorage.setItem(storageKey, box.hasClass(klass) ? "toggled" : "not-toggled");
}
box.click(toggle);
// Check the persistent state of the editor pop-up
// Note that localStorage does not necessarily support boolean values (ugh!)
// http://stackoverflow.com/questions/3263161/cannot-set-boolean-values-in-localstorage
var v = window.localStorage.getItem(storageKey);
if(v == "toggled" || !v) {
box.addClass(klass);
}
});
})(jQuery);
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-2097050-4']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
{% endblock %}
{% block rootrellink %}
<li><a href="https://github.com/giampaolo/psutil/"><img src="{{ pathto('_static/logo.png', 1) }}" style="height: 30px; vertical-align: middle; padding-right: 1em;" /> Project Homepage</a>{{ reldelim1 }}</li>
<li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li>
{% endblock %}
{% block footer %}
<div class="footer">
&copy; Copyright {{ copyright|e }}.
<br />
Last updated on {{ last_updated|e }}.
<br />
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}.
</div>
{% endblock %}

View File

@ -0,0 +1,187 @@
@import url("default.css");
body {
background-color: white;
margin-left: 1em;
margin-right: 1em;
}
div.related {
margin-bottom: 1.2em;
padding: 0.5em 0;
border-top: 1px solid #ccc;
margin-top: 0.5em;
}
div.related a:hover {
color: #0095C4;
}
div.related:first-child {
border-top: 0;
padding-top: 0;
border-bottom: 1px solid #ccc;
}
div.sphinxsidebar {
background-color: #eeeeee;
border-radius: 5px;
line-height: 130%;
font-size: smaller;
}
div.sphinxsidebar h3, div.sphinxsidebar h4 {
margin-top: 1.5em;
}
div.sphinxsidebarwrapper > h3:first-child {
margin-top: 0.2em;
}
div.sphinxsidebarwrapper > ul > li > ul > li {
margin-bottom: 0.4em;
}
div.sphinxsidebar a:hover {
color: #0095C4;
}
div.sphinxsidebar input {
font-family: 'Lucida Grande','Lucida Sans','DejaVu Sans',Arial,sans-serif;
border: 1px solid #999999;
font-size: smaller;
border-radius: 3px;
}
div.sphinxsidebar input[type=text] {
max-width: 150px;
}
div.body {
padding: 0 0 0 1.2em;
}
div.body p {
line-height: 140%;
}
div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
margin: 0;
border: 0;
padding: 0.3em 0;
}
div.body hr {
border: 0;
background-color: #ccc;
height: 1px;
}
div.body pre {
border-radius: 3px;
border: 1px solid #ac9;
}
div.body div.admonition, div.body div.impl-detail {
border-radius: 3px;
}
div.body div.impl-detail > p {
margin: 0;
}
div.body div.seealso {
border: 1px solid #dddd66;
}
div.body a {
color: #00608f;
}
div.body a:visited {
color: #30306f;
}
div.body a:hover {
color: #00B0E4;
}
tt, pre {
font-family: monospace, sans-serif;
font-size: 96.5%;
}
div.body tt {
border-radius: 3px;
}
div.body tt.descname {
font-size: 120%;
}
div.body tt.xref, div.body a tt {
font-weight: normal;
}
p.deprecated {
border-radius: 3px;
}
table.docutils {
border: 1px solid #ddd;
min-width: 20%;
border-radius: 3px;
margin-top: 10px;
margin-bottom: 10px;
}
table.docutils td, table.docutils th {
border: 1px solid #ddd !important;
border-radius: 3px;
}
table p, table li {
text-align: left !important;
}
table.docutils th {
background-color: #eee;
padding: 0.3em 0.5em;
}
table.docutils td {
background-color: white;
padding: 0.3em 0.5em;
}
table.footnote, table.footnote td {
border: 0 !important;
}
div.footer {
line-height: 150%;
margin-top: -2em;
text-align: right;
width: auto;
margin-right: 10px;
}
div.footer a:hover {
color: #0095C4;
}
div.body h1,
div.body h2,
div.body h3 {
background-color: #EAEAEA;
border-bottom: 1px solid #CCC;
padding-top: 2px;
padding-bottom: 2px;
padding-left: 5px;
margin-top: 5px;
margin-bottom: 5px;
}
div.body h2 {
padding-left:10px;
}

View File

@ -0,0 +1,23 @@
[theme]
inherit = default
stylesheet = pydoctheme.css
pygments_style = sphinx
[options]
bodyfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
headfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif
footerbgcolor = white
footertextcolor = #555555
relbarbgcolor = white
relbartextcolor = #666666
relbarlinkcolor = #444444
sidebarbgcolor = white
sidebartextcolor = #444444
sidebarlinkcolor = #444444
bgcolor = white
textcolor = #222222
linkcolor = #0090c0
visitedlinkcolor = #00608f
headtextcolor = #1a1a1a
headbgcolor = white
headlinkcolor = #aaaaaa

262
python/psutil/docs/conf.py Normal file
View File

@ -0,0 +1,262 @@
# -*- coding: utf-8 -*-
#
# psutil documentation build configuration file, created by
# sphinx-quickstart.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
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'")
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:
for line in f:
if line.startswith('__version__'):
ret = eval(line.strip().split(' = ')[1])
assert ret.count('.') == 2, ret
for num in ret.split('.'):
assert num.isdigit(), ret
return ret
else:
raise ValueError("couldn't find version string")
finally:
f.close()
VERSION = get_version()
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.coverage',
'sphinx.ext.pngmath',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_template']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = PROJECT_NAME
copyright = u('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
# built documents.
#
# The short X.Y version.
version = VERSION
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
autodoc_docstring_signature = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme = 'pydoctheme'
html_theme_options = {'collapsiblesidebar': True}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ["_themes"]
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = "{project} {version} documentation".format(**locals())
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = 'logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_static/favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
html_sidebars = {
'index': 'indexsidebar.html',
'**': ['globaltoc.html',
'relations.html',
'sourcelink.html',
'searchbox.html']
}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {
# 'index': 'indexcontent.html',
# }
# If false, no module index is generated.
html_domain_indices = False
# If false, no index is generated.
html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = '%s-doc' % PROJECT_NAME
# -- Options for LaTeX output ------------------------------------------------
# The paper size ('letter' or 'a4').
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
('index', '%s.tex' % PROJECT_NAME,
u('%s documentation') % PROJECT_NAME, AUTHOR),
]
# The name of an image file (relative to this directory) to place at
# the top of the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Additional stuff for the LaTeX preamble.
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output ------------------------------------------
# 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)
]
# If true, show URL addresses after external links.
# man_show_urls = False

1247
python/psutil/docs/index.rst Normal file

File diff suppressed because it is too large Load Diff

242
python/psutil/docs/make.bat Normal file
View File

@ -0,0 +1,242 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\psutil.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\psutil.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

View File

@ -6,6 +6,13 @@
"""
List all mounted disk partitions a-la "df -h" command.
$ python examples/disk_usage.py
Device Total Used Free Use % Type Mount
/dev/sdb3 18.9G 14.7G 3.3G 77% ext4 /
/dev/sda6 345.9G 83.8G 244.5G 24% ext4 /home
/dev/sda1 296.0M 43.1M 252.9M 14% vfat /boot/efi
/dev/sda2 600.0M 312.4M 287.6M 52% fuseblk /media/Recovery
"""
import sys
@ -13,6 +20,7 @@ import os
import psutil
from psutil._compat import print_
def bytes2human(n):
# http://code.activestate.com/recipes/578019
# >>> bytes2human(10000)
@ -22,7 +30,7 @@ def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
@ -32,19 +40,24 @@ 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' and 'cdrom' in part.opts:
# may raise ENOENT if there's no cd-rom in the drive
continue
if os.name == 'nt':
if 'cdrom' in part.opts or part.fstype == '':
# skip cd-rom drives with no disk in it; they may raise
# ENOENT, pop-up a Windows GUI error for a non-ready
# partition or just hang.
continue
usage = psutil.disk_usage(part.mountpoint)
print_(templ % (part.device,
bytes2human(usage.total),
bytes2human(usage.used),
bytes2human(usage.free),
int(usage.percent),
part.fstype,
part.mountpoint))
print_(templ % (
part.device,
bytes2human(usage.total),
bytes2human(usage.used),
bytes2human(usage.free),
int(usage.percent),
part.fstype,
part.mountpoint))
if __name__ == '__main__':
sys.exit(main())

View File

@ -6,26 +6,37 @@
"""
A clone of 'free' cmdline utility.
$ python examples/free.py
total used free shared buffers cache
Mem: 10125520 8625996 1499524 0 349500 3307836
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 % ('Mem:', int(virt.total / 1024),
int(virt.used / 1024),
int(virt.free / 1024),
int(getattr(virt, 'shared', 0) / 1024),
int(getattr(virt, 'buffers', 0) / 1024),
int(getattr(virt, 'cached', 0) / 1024)))
print_(templ % ('Swap:', int(swap.total / 1024),
int(swap.used / 1024),
int(swap.free / 1024),
'', '', ''))
print_(templ % (
'Mem:',
int(virt.total / 1024),
int(virt.used / 1024),
int(virt.free / 1024),
int(getattr(virt, 'shared', 0) / 1024),
int(getattr(virt, 'buffers', 0) / 1024),
int(getattr(virt, 'cached', 0) / 1024)))
print_(templ % (
'Swap:', int(swap.total / 1024),
int(swap.used / 1024),
int(swap.free / 1024),
'',
'',
''))
if __name__ == '__main__':
main()

View File

@ -12,13 +12,28 @@ It works on Linux only (FreeBSD and OSX are missing support for IO
counters).
It doesn't work on Windows as curses module is required.
Example output:
$ python examples/iotop.py
Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s
PID USER DISK READ DISK WRITE COMMAND
13155 giampao 0.00 B/s 428.00 K/s /usr/bin/google-chrome-beta
3260 giampao 0.00 B/s 0.00 B/s bash
3779 giampao 0.00 B/s 0.00 B/s gnome-session --session=ubuntu
3830 giampao 0.00 B/s 0.00 B/s /usr/bin/dbus-launch
3831 giampao 0.00 B/s 0.00 B/s //bin/dbus-daemon --fork --print-pid 5
3841 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi-bus-launcher
3845 giampao 0.00 B/s 0.00 B/s /bin/dbus-daemon
3848 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi2-core/at-spi2-registryd
3862 giampao 0.00 B/s 0.00 B/s /usr/lib/gnome-settings-daemon
Author: Giampaolo Rodola' <g.rodola@gmail.com>
"""
import os
import sys
import psutil
if not hasattr(psutil.Process, 'get_io_counters') or os.name != 'posix':
if not hasattr(psutil.Process, 'io_counters') or os.name != 'posix':
sys.exit('platform not supported')
import time
import curses
@ -37,6 +52,7 @@ atexit.register(tear_down)
curses.endwin()
lineno = 0
def print_line(line, highlight=False):
"""A thin wrapper around curses's addstr()."""
global lineno
@ -65,13 +81,14 @@ def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.2f %s/s' % (value, s)
return '%.2f B/s' % (n)
def poll(interval):
"""Calculate IO usage by comparing IO statics before and
after the interval.
@ -82,7 +99,7 @@ def poll(interval):
procs = [p for p in psutil.process_iter()]
for p in procs[:]:
try:
p._before = p.get_io_counters()
p._before = p.io_counters()
except psutil.Error:
procs.remove(p)
continue
@ -94,11 +111,11 @@ def poll(interval):
# then retrieve the same info again
for p in procs[:]:
try:
p._after = p.get_io_counters()
p._cmdline = ' '.join(p.cmdline)
p._after = p.io_counters()
p._cmdline = ' '.join(p.cmdline())
if not p._cmdline:
p._cmdline = p.name
p._username = p.username
p._cmdline = p.name()
p._username = p.username()
except psutil.NoSuchProcess:
procs.remove(p)
disks_after = psutil.disk_io_counters()
@ -134,17 +151,19 @@ def refresh_window(procs, disks_read, disks_write):
print_line(header, highlight=True)
for p in procs:
line = templ % (p.pid,
p._username[:7],
bytes2human(p._read_per_sec),
bytes2human(p._write_per_sec),
p._cmdline)
line = templ % (
p.pid,
p._username[:7],
bytes2human(p._read_per_sec),
bytes2human(p._write_per_sec),
p._cmdline)
try:
print_line(line)
except curses.error:
break
win.refresh()
def main():
try:
interval = 0

View File

@ -12,6 +12,7 @@ import os
import sys
import psutil
def main():
if len(sys.argv) != 2:
sys.exit('usage: %s name' % __file__)
@ -20,7 +21,7 @@ def main():
killed = []
for proc in psutil.process_iter():
if proc.name == NAME and proc.pid != os.getpid():
if proc.name() == NAME and proc.pid != os.getpid():
proc.kill()
killed.append(proc.pid)
if not killed:

View File

@ -6,21 +6,59 @@
"""
Print system memory information.
$ python examples/meminfo.py
MEMORY
------
Total : 9.7G
Available : 4.9G
Percent : 49.0
Used : 8.2G
Free : 1.4G
Active : 5.6G
Inactive : 2.1G
Buffers : 341.2M
Cached : 3.2G
SWAP
----
Total : 0B
Used : 0B
Free : 0B
Percent : 0.0
Sin : 0B
Sout : 0B
"""
import psutil
from psutil._compat import print_
def to_meg(n):
return str(int(n / 1024 / 1024)) + "M"
def bytes2human(n):
# http://code.activestate.com/recipes/578019
# >>> bytes2human(10000)
# '9.8K'
# >>> bytes2human(100001221)
# '95.4M'
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.1f%s' % (value, s)
return "%sB" % n
def pprint_ntuple(nt):
for name in nt._fields:
value = getattr(nt, name)
if name != 'percent':
value = to_meg(value)
value = bytes2human(value)
print_('%-10s : %7s' % (name.capitalize(), value))
def main():
print_('MEMORY\n------')
pprint_ntuple(psutil.virtual_memory())

View File

@ -5,7 +5,18 @@
# found in the LICENSE file.
"""
A clone of 'netstat'.
A clone of 'netstat -antp' on Linux.
$ python examples/netstat.py
Proto Local address Remote address Status PID Program name
tcp 127.0.0.1:48256 127.0.0.1:45884 ESTABLISHED 13646 chrome
tcp 127.0.0.1:47073 127.0.0.1:45884 ESTABLISHED 13646 chrome
tcp 127.0.0.1:47072 127.0.0.1:45884 ESTABLISHED 13646 chrome
tcp 127.0.0.1:45884 - LISTEN 13651 GoogleTalkPlugi
tcp 127.0.0.1:60948 - LISTEN 13651 GoogleTalkPlugi
tcp 172.17.42.1:49102 127.0.0.1:19305 CLOSE_WAIT 13651 GoogleTalkPlugi
tcp 172.17.42.1:55797 127.0.0.1:443 CLOSE_WAIT 13651 GoogleTalkPlugi
...
"""
import socket
@ -17,36 +28,38 @@ from psutil._compat import print_
AD = "-"
AF_INET6 = getattr(socket, 'AF_INET6', object())
proto_map = {(AF_INET, SOCK_STREAM) : 'tcp',
(AF_INET6, SOCK_STREAM) : 'tcp6',
(AF_INET, SOCK_DGRAM) : 'udp',
(AF_INET6, SOCK_DGRAM) : 'udp6'}
proto_map = {
(AF_INET, SOCK_STREAM): 'tcp',
(AF_INET6, SOCK_STREAM): 'tcp6',
(AF_INET, SOCK_DGRAM): 'udp',
(AF_INET6, SOCK_DGRAM): 'udp6',
}
def main():
templ = "%-5s %-22s %-22s %-13s %-6s %s"
print_(templ % ("Proto", "Local addr", "Remote addr", "Status", "PID",
"Program name"))
templ = "%-5s %-30s %-30s %-13s %-6s %s"
print_(templ % (
"Proto", "Local address", "Remote address", "Status", "PID",
"Program name"))
proc_names = {}
for p in psutil.process_iter():
name = '?'
try:
name = p.name
cons = p.get_connections(kind='inet')
except psutil.AccessDenied:
print_(templ % (AD, AD, AD, AD, p.pid, name))
except psutil.NoSuchProcess:
continue
else:
for c in cons:
raddr = ""
laddr = "%s:%s" % (c.laddr)
if c.raddr:
raddr = "%s:%s" % (c.raddr)
print_(templ % (proto_map[(c.family, c.type)],
laddr,
raddr,
str(c.status),
p.pid,
name[:15]))
proc_names[p.pid] = p.name()
except psutil.Error:
pass
for c in psutil.net_connections(kind='inet'):
laddr = "%s:%s" % (c.laddr)
raddr = ""
if c.raddr:
raddr = "%s:%s" % (c.raddr)
print_(templ % (
proto_map[(c.family, c.type)],
laddr,
raddr or AD,
c.status,
c.pid or AD,
proc_names.get(c.pid, '?')[:15],
))
if __name__ == '__main__':
main()

View File

@ -10,14 +10,33 @@
Shows real-time network statistics.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python examples/nettop.py
-----------------------------------------------------------
total bytes: sent: 1.49 G received: 4.82 G
total packets: sent: 7338724 received: 8082712
wlan0 TOTAL PER-SEC
-----------------------------------------------------------
bytes-sent 1.29 G 0.00 B/s
bytes-recv 3.48 G 0.00 B/s
pkts-sent 7221782 0
pkts-recv 6753724 0
eth1 TOTAL PER-SEC
-----------------------------------------------------------
bytes-sent 131.77 M 0.00 B/s
bytes-recv 1.28 G 0.00 B/s
pkts-sent 0 0
pkts-recv 1214470 0
"""
import sys
import os
if os.name != 'posix':
sys.exit('platform not supported')
import curses
import atexit
import curses
import time
import psutil
@ -35,6 +54,7 @@ atexit.register(tear_down)
curses.endwin()
lineno = 0
def print_line(line, highlight=False):
"""A thin wrapper around curses's addstr()."""
global lineno
@ -63,13 +83,14 @@ def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.2f %s' % (value, s)
return '%.2f B' % (n)
def poll(interval):
"""Retrieve raw stats within an interval window."""
tot_before = psutil.net_io_counters()
@ -86,14 +107,12 @@ def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
global lineno
# totals
print_line("total bytes: sent: %-10s received: %s" \
% (bytes2human(tot_after.bytes_sent),
bytes2human(tot_after.bytes_recv))
print_line("total bytes: sent: %-10s received: %s" % (
bytes2human(tot_after.bytes_sent),
bytes2human(tot_after.bytes_recv))
)
print_line("total packets: sent: %-10s received: %s" \
% (tot_after.packets_sent, tot_after.packets_recv)
)
print_line("total packets: sent: %-10s received: %s" % (
tot_after.packets_sent, tot_after.packets_recv))
# per-network interface details: let's sort network interfaces so
# that the ones which generated more traffic are shown first
@ -108,12 +127,14 @@ def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
print_line(templ % (
"bytes-sent",
bytes2human(stats_after.bytes_sent),
bytes2human(stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
bytes2human(
stats_after.bytes_sent - stats_before.bytes_sent) + '/s',
))
print_line(templ % (
"bytes-recv",
bytes2human(stats_after.bytes_recv),
bytes2human(stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
bytes2human(
stats_after.bytes_recv - stats_before.bytes_recv) + '/s',
))
print_line(templ % (
"pkts-sent",
@ -133,7 +154,7 @@ def refresh_window(tot_before, tot_after, pnic_before, pnic_after):
def main():
try:
interval = 0
while 1:
while True:
args = poll(interval)
refresh_window(*args)
interval = 1

View File

@ -7,6 +7,27 @@
"""
A clone of 'pmap' utility on Linux, 'vmmap' on OSX and 'procstat -v' on BSD.
Report memory map of a process.
$ python examples/pmap.py 32402
pid=32402, name=hg
Address RSS Mode Mapping
0000000000400000 1200K r-xp /usr/bin/python2.7
0000000000838000 4K r--p /usr/bin/python2.7
0000000000839000 304K rw-p /usr/bin/python2.7
00000000008ae000 68K rw-p [anon]
000000000275e000 5396K rw-p [heap]
00002b29bb1e0000 124K r-xp /lib/x86_64-linux-gnu/ld-2.17.so
00002b29bb203000 8K rw-p [anon]
00002b29bb220000 528K rw-p [anon]
00002b29bb2d8000 768K rw-p [anon]
00002b29bb402000 4K r--p /lib/x86_64-linux-gnu/ld-2.17.so
00002b29bb403000 8K rw-p /lib/x86_64-linux-gnu/ld-2.17.so
00002b29bb405000 60K r-xp /lib/x86_64-linux-gnu/libpthread-2.17.so
00002b29bb41d000 0K ---p /lib/x86_64-linux-gnu/libpthread-2.17.so
00007fff94be6000 48K rw-p [stack]
00007fff94dd1000 4K r-xp [vdso]
ffffffffff600000 0K r-xp [vsyscall]
...
"""
import sys
@ -14,20 +35,22 @@ import sys
import psutil
from psutil._compat import print_
def main():
if len(sys.argv) != 2:
sys.exit('usage: pmap pid')
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"))
total_rss = 0
for m in p.get_memory_maps(grouped=False):
for m in p.memory_maps(grouped=False):
total_rss += m.rss
print_(templ % (m.addr.split('-')[0].zfill(16),
str(m.rss / 1024) + 'K' ,
m.perms,
m.path))
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', '', ''))

View File

@ -6,38 +6,63 @@
"""
Print detailed information about a process.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python examples/process_detail.py
pid 820
name python
exe /usr/bin/python2.7
parent 29613 (bash)
cmdline python examples/process_detail.py
started 2014-41-27 03:41
user giampaolo
uids real=1000, effective=1000, saved=1000
gids real=1000, effective=1000, saved=1000
terminal /dev/pts/17
cwd /ssd/svn/psutil
memory 0.1% (resident=10.6M, virtual=58.5M)
cpu 0.0% (user=0.09, system=0.0)
status running
niceness 0
num threads 1
I/O bytes-read=0B, bytes-written=0B
open files
running threads id=820, user-time=0.09, sys-time=0.0
"""
import os
import datetime
import os
import socket
import sys
import psutil
POSIX = os.name == 'posix'
def convert_bytes(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = float(n) / prefix[s]
return '%.1f%s' % (value, s)
return "%sB" % n
def print_(a, b):
if sys.stdout.isatty() and os.name == 'posix':
fmt = '\x1b[1;32m%-17s\x1b[0m %s' %(a, b)
if sys.stdout.isatty() and POSIX:
fmt = '\x1b[1;32m%-17s\x1b[0m %s' % (a, b)
else:
fmt = '%-15s %s' %(a, b)
fmt = '%-15s %s' % (a, b)
# python 2/3 compatibility layer
sys.stdout.write(fmt + '\n')
sys.stdout.flush()
def run(pid):
ACCESS_DENIED = ''
try:
@ -47,20 +72,21 @@ def run(pid):
sys.exit(str(sys.exc_info()[1]))
try:
if p.parent:
parent = '(%s)' % p.parent.name
parent = p.parent()
if parent:
parent = '(%s)' % parent.name()
else:
parent = ''
except psutil.Error:
parent = ''
started = datetime.datetime.fromtimestamp(pinfo['create_time']
).strftime('%Y-%M-%d %H:%M')
started = datetime.datetime.fromtimestamp(
pinfo['create_time']).strftime('%Y-%m-%d %H:%M')
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))
children = p.get_children()
round(pinfo['memory_percent'], 1),
convert_bytes(pinfo['memory_info'].rss),
convert_bytes(pinfo['memory_info'].vms))
children = p.children()
print_('pid', pinfo['pid'])
print_('name', pinfo['name'])
@ -69,41 +95,42 @@ def run(pid):
print_('cmdline', ' '.join(pinfo['cmdline']))
print_('started', started)
print_('user', pinfo['username'])
if os.name == 'posix' and pinfo['uids'] and pinfo['gids']:
if POSIX and pinfo['uids'] and pinfo['gids']:
print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids'])
if os.name == 'posix' and pinfo['gids']:
if POSIX and pinfo['gids']:
print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids'])
if os.name == 'posix':
if POSIX:
print_('terminal', pinfo['terminal'] or '')
if hasattr(p, 'getcwd'):
print_('cwd', pinfo['cwd'])
print_('memory', mem)
print_('cpu', '%s%% (user=%s, system=%s)' % (pinfo['cpu_percent'],
getattr(pinfo['cpu_times'], 'user', '?'),
getattr(pinfo['cpu_times'], 'system', '?')))
print_('cpu', '%s%% (user=%s, system=%s)' % (
pinfo['cpu_percent'],
getattr(pinfo['cpu_times'], 'user', '?'),
getattr(pinfo['cpu_times'], 'system', '?')))
print_('status', pinfo['status'])
print_('niceness', pinfo['nice'])
print_('num threads', pinfo['num_threads'])
if io != ACCESS_DENIED:
print_('I/O', 'bytes-read=%s, bytes-written=%s' % \
(convert_bytes(io.read_bytes),
convert_bytes(io.write_bytes)))
print_('I/O', 'bytes-read=%s, bytes-written=%s' % (
convert_bytes(io.read_bytes),
convert_bytes(io.write_bytes)))
if children:
print_('children', '')
for child in children:
print_('', 'pid=%s name=%s' % (child.pid, child.name))
print_('', 'pid=%s name=%s' % (child.pid, child.name()))
if pinfo['open_files'] != ACCESS_DENIED:
print_('open files', '')
for file in pinfo['open_files']:
print_('', 'fd=%s %s ' % (file.fd, file.path))
print_('', 'fd=%s %s ' % (file.fd, file.path))
if pinfo['threads']:
print_('running threads', '')
for thread in pinfo['threads']:
print_('', 'id=%s, user-time=%s, sys-time=%s' \
% (thread.id, thread.user_time, thread.system_time))
if pinfo['connections'] != ACCESS_DENIED:
print_('', 'id=%s, user-time=%s, sys-time=%s' % (
thread.id, thread.user_time, thread.system_time))
if pinfo['connections'] not in (ACCESS_DENIED, []):
print_('open connections', '')
for conn in pinfo['connections']:
if conn.type == socket.SOCK_STREAM:
@ -117,8 +144,9 @@ def run(pid):
rip, rport = '*', '*'
else:
rip, rport = conn.raddr
print_('', '%s:%s -> %s:%s type=%s status=%s' \
% (lip, lport, rip, rport, type, conn.status))
print_('', '%s:%s -> %s:%s type=%s status=%s' % (
lip, lport, rip, rport, type, conn.status))
def main(argv=None):
if argv is None:

View File

@ -0,0 +1,81 @@
#!/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 'ps -aux' on UNIX.
$ python examples/ps.py
...
"""
import datetime
import os
import time
import psutil
from psutil._compat import print_
def main():
today_day = datetime.date.today()
templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s"
attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times',
'create_time', 'memory_info']
if os.name == 'posix':
attrs.append('uids')
attrs.append('terminal')
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='')
except psutil.NoSuchProcess:
pass
else:
if pinfo['create_time']:
ctime = datetime.datetime.fromtimestamp(pinfo['create_time'])
if ctime.date() == today_day:
ctime = ctime.strftime("%H:%M")
else:
ctime = ctime.strftime("%b%d")
else:
ctime = ''
cputime = time.strftime("%M:%S",
time.localtime(sum(pinfo['cpu_times'])))
try:
user = p.username()
except KeyError:
if os.name == 'posix':
if pinfo['uids']:
user = str(pinfo['uids'].real)
else:
user = ''
else:
raise
except psutil.Error:
user = ''
if os.name == 'nt' and '\\' in user:
user = user.split('\\')[1]
vms = pinfo['memory_info'] and \
int(pinfo['memory_info'].vms / 1024) or '?'
rss = pinfo['memory_info'] and \
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 '?'))
if __name__ == '__main__':
main()

View File

@ -8,15 +8,39 @@
A clone of top / htop.
Author: Giampaolo Rodola' <g.rodola@gmail.com>
$ python examples/top.py
CPU0 [| ] 4.9%
CPU1 [||| ] 7.8%
CPU2 [ ] 2.0%
CPU3 [||||| ] 13.9%
Mem [||||||||||||||||||| ] 49.8% 4920M/9888M
Swap [ ] 0.0% 0M/0M
Processes: 287 (running=1 sleeping=286)
Load average: 0.34 0.54 0.46 Uptime: 3 days, 10:16:37
PID USER NI VIRT RES CPU% MEM% TIME+ NAME
------------------------------------------------------------
989 giampaol 0 66M 12M 7.4 0.1 0:00.61 python
2083 root 0 506M 159M 6.5 1.6 0:29.26 Xorg
4503 giampaol 0 599M 25M 6.5 0.3 3:32.60 gnome-terminal
3868 giampaol 0 358M 8M 2.8 0.1 23:12.60 pulseaudio
3936 giampaol 0 1G 111M 2.8 1.1 33:41.67 compiz
4401 giampaol 0 536M 141M 2.8 1.4 35:42.73 skype
4047 giampaol 0 743M 76M 1.8 0.8 42:03.33 unity-panel-service
13155 giampaol 0 1G 280M 1.8 2.8 41:57.34 chrome
10 root 0 0B 0B 0.9 0.0 4:01.81 rcu_sched
339 giampaol 0 1G 113M 0.9 1.1 8:15.73 chrome
...
"""
import os
import sys
if os.name != 'posix':
sys.exit('platform not supported')
import time
import curses
import atexit
import curses
import time
from datetime import datetime, timedelta
import psutil
@ -34,6 +58,7 @@ atexit.register(tear_down)
curses.endwin()
lineno = 0
def print_line(line, highlight=False):
"""A thin wrapper around curses's addstr()."""
global lineno
@ -62,13 +87,14 @@ def bytes2human(n):
symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
prefix = {}
for i, s in enumerate(symbols):
prefix[s] = 1 << (i+1)*10
prefix[s] = 1 << (i + 1) * 10
for s in reversed(symbols):
if n >= prefix[s]:
value = int(float(n) / prefix[s])
return '%s%s' % (value, s)
return "%sB" % n
def poll(interval):
# sleep some time
time.sleep(interval)
@ -76,32 +102,35 @@ def poll(interval):
procs_status = {}
for p in psutil.process_iter():
try:
p.dict = p.as_dict(['username', 'get_nice', 'get_memory_info',
'get_memory_percent', 'get_cpu_percent',
'get_cpu_times', 'name', 'status'])
p.dict = p.as_dict(['username', 'nice', 'memory_info',
'memory_percent', 'cpu_percent',
'cpu_times', 'name', 'status'])
try:
procs_status[str(p.dict['status'])] += 1
procs_status[p.dict['status']] += 1
except KeyError:
procs_status[str(p.dict['status'])] = 1
procs_status[p.dict['status']] = 1
except psutil.NoSuchProcess:
pass
else:
procs.append(p)
# return processes sorted by CPU percent usage
processes = sorted(procs, key=lambda p: p.dict['cpu_percent'], reverse=True)
processes = sorted(procs, key=lambda p: p.dict['cpu_percent'],
reverse=True)
return (processes, procs_status)
def print_header(procs_status, num_procs):
"""Print system-related info, above the process list."""
def get_dashes(perc):
dashes = "|" * int((float(perc) / 10 * 4))
dashes = "|" * int((float(perc) / 10 * 4))
empty_dashes = " " * (40 - len(dashes))
return dashes, empty_dashes
# cpu usage
for cpu_num, perc in enumerate(psutil.cpu_percent(interval=0, percpu=True)):
percs = psutil.cpu_percent(interval=0, percpu=True)
for cpu_num, perc in enumerate(percs):
dashes, empty_dashes = get_dashes(perc)
print_line(" CPU%-2s [%s%s] %5s%%" % (cpu_num, dashes, empty_dashes,
perc))
@ -135,12 +164,13 @@ def print_header(procs_status, num_procs):
st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1)
print_line(" Processes: %s (%s)" % (num_procs, ' '.join(st)))
# load average, uptime
uptime = datetime.now() - datetime.fromtimestamp(psutil.BOOT_TIME)
uptime = datetime.now() - datetime.fromtimestamp(psutil.boot_time())
av1, av2, av3 = os.getloadavg()
line = " Load average: %.2f %.2f %.2f Uptime: %s" \
% (av1, av2, av3, str(uptime).split('.')[0])
% (av1, av2, av3, str(uptime).split('.')[0])
print_line(line)
def refresh_window(procs, procs_status):
"""Print results on screen by using curses."""
curses.endwin()
@ -154,7 +184,7 @@ def refresh_window(procs, procs_status):
for p in procs:
# TIME+ column shows process CPU cumulative time and it
# is expressed as: "mm:ss.ms"
if p.dict['cpu_times'] != None:
if p.dict['cpu_times'] is not None:
ctime = timedelta(seconds=sum(p.dict['cpu_times']))
ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60,
str((ctime.seconds % 60)).zfill(2),

View File

@ -7,9 +7,14 @@
"""
A clone of 'who' command; print information about users who are
currently logged in.
$ python examples/who.py
giampaolo tty7 2014-02-23 17:25 (:0)
giampaolo pts/7 2014-02-24 18:25 (:192.168.1.56)
giampaolo pts/8 2014-02-24 18:25 (:0)
giampaolo pts/9 2014-02-27 01:32 (:0)
"""
import sys
from datetime import datetime
import psutil
@ -17,14 +22,13 @@ from psutil._compat import print_
def main():
users = psutil.get_users()
users = psutil.users()
for user in users:
print_("%-15s %-15s %s (%s)" % \
(user.name,
user.terminal or '-',
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
user.host)
)
print_("%-15s %-15s %s (%s)" % (
user.name,
user.terminal or '-',
datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"),
user.host))
if __name__ == '__main__':
main()

230
python/psutil/make.bat Normal file
View File

@ -0,0 +1,230 @@
@echo off
rem ==========================================================================
rem Shortcuts for various tasks, emulating UNIX "make" on Windows.
rem It is primarly intended as a shortcut for compiling / installing
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
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 ==========================================================================
if "%PYTHON%" == "" (
set PYTHON=C:\Python27\python.exe
)
if "%TSCRIPT%" == "" (
set TSCRIPT=test\test_psutil.py
)
rem Needed to compile using Mingw.
set PATH=C:\MinGW\bin;%PATH%
rem Needed to locate the .pypirc file and upload exes on PYPI.
set HOME=%USERPROFILE%
rem ==========================================================================
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 clean clean build files
echo install compile and install
echo memtest run memory leak tests
echo setup-env install pip, unittest2, wheels for all python versions
echo test run 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
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)
for /r %%R in (*.orig) do if exist %%R (del /s %%R)
for /r %%R in (*.bak) do if exist %%R (del /s %%R)
for /r %%R in (*.rej) do if exist %%R (del /s %%R)
if exist psutil.egg-info (rmdir /S /Q psutil.egg-info)
if exist build (rmdir /S /Q build)
if exist dist (rmdir /S /Q dist)
goto :eof
)
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
)
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
)
goto :eof
)
if "%1" == "uninstall" (
:uninstall
for %%A in ("%PYTHON%") do (
set folder=%%~dpA
)
for /F "delims=" %%i in ('dir /b %folder%\Lib\site-packages\*psutil*') do (
rmdir /S /Q %folder%\Lib\site-packages\%%i
)
goto :eof
)
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)
"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
echo OK
goto :eof
)
if "%1" == "upload-exes" (
: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
echo OK
goto :eof
)
if "%1" == "setup-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
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
goto :eof
)
goto :help
:error
echo last command exited with error code %errorlevel%
exit /b %errorlevel%
goto :eof

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#/usr/bin/env python
# /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
@ -7,13 +7,52 @@
"""Common objects shared by all _ps* modules."""
from __future__ import division
import sys
import os
import stat
import errno
import os
import socket
import stat
import sys
import warnings
try:
import threading
except ImportError:
import dummy_threading as threading
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
from psutil._compat import namedtuple, wraps
# --- constants
AF_INET6 = getattr(socket, 'AF_INET6', None)
AF_UNIX = getattr(socket, 'AF_UNIX', None)
STATUS_RUNNING = "running"
STATUS_SLEEPING = "sleeping"
STATUS_DISK_SLEEP = "disk-sleep"
STATUS_STOPPED = "stopped"
STATUS_TRACING_STOP = "tracing-stop"
STATUS_ZOMBIE = "zombie"
STATUS_DEAD = "dead"
STATUS_WAKE_KILL = "wake-kill"
STATUS_WAKING = "waking"
STATUS_IDLE = "idle" # BSD
STATUS_LOCKED = "locked" # BSD
STATUS_WAITING = "waiting" # BSD
CONN_ESTABLISHED = "ESTABLISHED"
CONN_SYN_SENT = "SYN_SENT"
CONN_SYN_RECV = "SYN_RECV"
CONN_FIN_WAIT1 = "FIN_WAIT1"
CONN_FIN_WAIT2 = "FIN_WAIT2"
CONN_TIME_WAIT = "TIME_WAIT"
CONN_CLOSE = "CLOSE"
CONN_CLOSE_WAIT = "CLOSE_WAIT"
CONN_LAST_ACK = "LAST_ACK"
CONN_LISTEN = "LISTEN"
CONN_CLOSING = "CLOSING"
CONN_NONE = "NONE"
from psutil._compat import namedtuple, long, wraps
# --- functions
@ -28,61 +67,49 @@ def usage_percent(used, total, _round=None):
else:
return ret
class constant(int):
"""A constant type; overrides base int to provide a useful name on str()."""
def __new__(cls, value, name, doc=None):
inst = super(constant, cls).__new__(cls, value)
inst._name = name
if doc is not None:
inst.__doc__ = doc
return inst
def memoize(fun):
"""A simple memoize decorator for functions supporting (hashable)
positional arguments.
It also provides a cache_clear() function for clearing the cache:
def __str__(self):
return self._name
def __eq__(self, other):
# Use both int or str values when comparing for equality
# (useful for serialization):
# >>> st = constant(0, "running")
# >>> st == 0
# True
# >>> st == 'running'
# True
if isinstance(other, int):
return int(self) == other
if isinstance(other, long):
return long(self) == other
if isinstance(other, str):
return self._name == other
return False
def __ne__(self, other):
return not self.__eq__(other)
def memoize(f):
"""A simple memoize decorator for functions."""
cache= {}
def memf(*x):
if x not in cache:
cache[x] = f(*x)
return cache[x]
return memf
class cached_property(object):
"""A memoize decorator for class properties."""
enabled = True
def __init__(self, func):
self.func = func
def __get__(self, instance, type):
ret = self.func(instance)
if self.enabled:
instance.__dict__[self.func.__name__] = ret
>>> @memoize
... def foo()
... return 1
...
>>> foo()
1
>>> foo.cache_clear()
>>>
"""
@wraps(fun)
def wrapper(*args, **kwargs):
key = (args, frozenset(sorted(kwargs.items())))
lock.acquire()
try:
try:
return cache[key]
except KeyError:
ret = cache[key] = fun(*args, **kwargs)
finally:
lock.release()
return ret
# http://goo.gl/jYLvf
def cache_clear():
"""Clear cache."""
lock.acquire()
try:
cache.clear()
finally:
lock.release()
lock = threading.RLock()
cache = {}
wrapper.cache_clear = cache_clear
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):
@ -101,6 +128,24 @@ def deprecated(replacement=None):
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:
@ -117,102 +162,97 @@ def isfile_strict(path):
return stat.S_ISREG(st.st_mode)
# --- constants
STATUS_RUNNING = constant(0, "running")
STATUS_SLEEPING = constant(1, "sleeping")
STATUS_DISK_SLEEP = constant(2, "disk sleep")
STATUS_STOPPED = constant(3, "stopped")
STATUS_TRACING_STOP = constant(4, "tracing stop")
STATUS_ZOMBIE = constant(5, "zombie")
STATUS_DEAD = constant(6, "dead")
STATUS_WAKE_KILL = constant(7, "wake kill")
STATUS_WAKING = constant(8, "waking")
STATUS_IDLE = constant(9, "idle") # BSD
STATUS_LOCKED = constant(10, "locked") # BSD
STATUS_WAITING = constant(11, "waiting") # BSD
CONN_ESTABLISHED = constant(0, "ESTABLISHED")
CONN_SYN_SENT = constant(1, "SYN_SENT")
CONN_SYN_RECV = constant(2, "SYN_RECV")
CONN_FIN_WAIT1 = constant(3, "FIN_WAIT1")
CONN_FIN_WAIT2 = constant(4, "FIN_WAIT2")
CONN_TIME_WAIT = constant(5, "TIME_WAIT")
CONN_CLOSE = constant(6, "CLOSE")
CONN_CLOSE_WAIT = constant(7, "CLOSE_WAIT")
CONN_LAST_ACK = constant(8, "LAST_ACK")
CONN_LISTEN = constant(9, "LISTEN")
CONN_CLOSING = constant(10, "CLOSING")
CONN_NONE = constant(20, "NONE")
# --- Process.get_connections() 'kind' parameter mapping
import socket
from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM
AF_INET6 = getattr(socket, 'AF_INET6', None)
AF_UNIX = getattr(socket, 'AF_UNIX', None)
# --- Process.connections() 'kind' parameter mapping
conn_tmap = {
"all" : ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
"tcp" : ([AF_INET, AF_INET6], [SOCK_STREAM]),
"tcp4" : ([AF_INET], [SOCK_STREAM]),
"udp" : ([AF_INET, AF_INET6], [SOCK_DGRAM]),
"udp4" : ([AF_INET], [SOCK_DGRAM]),
"inet" : ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
"inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]),
"inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
"all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
"tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]),
"tcp4": ([AF_INET], [SOCK_STREAM]),
"udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]),
"udp4": ([AF_INET], [SOCK_DGRAM]),
"inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
"inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]),
"inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]),
}
if AF_INET6 is not None:
conn_tmap.update({
"tcp6" : ([AF_INET6], [SOCK_STREAM]),
"udp6" : ([AF_INET6], [SOCK_DGRAM]),
"tcp6": ([AF_INET6], [SOCK_STREAM]),
"udp6": ([AF_INET6], [SOCK_DGRAM]),
})
if AF_UNIX is not None:
conn_tmap.update({
"unix" : ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]),
})
del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket
# --- namedtuples
# system
nt_sysmeminfo = namedtuple('usage', 'total used free percent')
# XXX - would 'available' be better than 'free' as for virtual_memory() nt?
nt_swapmeminfo = namedtuple('swap', 'total used free percent sin sout')
nt_diskinfo = namedtuple('usage', 'total used free percent')
nt_partition = namedtuple('partition', 'device mountpoint fstype opts')
nt_net_iostat = namedtuple('iostat',
'bytes_sent bytes_recv packets_sent packets_recv errin errout dropin dropout')
nt_disk_iostat = namedtuple('iostat', 'read_count write_count read_bytes write_bytes read_time write_time')
nt_user = namedtuple('user', 'name terminal host started')
# --- namedtuples for psutil.* system-related functions
# processes
nt_meminfo = namedtuple('meminfo', 'rss vms')
nt_cputimes = namedtuple('cputimes', 'user system')
nt_openfile = namedtuple('openfile', 'path fd')
nt_thread = namedtuple('thread', 'id user_time system_time')
nt_uids = namedtuple('user', 'real effective saved')
nt_gids = namedtuple('group', 'real effective saved')
nt_io = namedtuple('io', 'read_count write_count read_bytes write_bytes')
nt_ionice = namedtuple('ionice', 'ioclass value')
nt_ctxsw = namedtuple('amount', 'voluntary involuntary')
# psutil.swap_memory()
sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin',
'sout'])
# psutil.disk_usage()
sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent'])
# psutil.disk_io_counters()
sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_time', 'write_time'])
# psutil.disk_partitions()
sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
# psutil.net_io_counters()
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
'packets_sent', 'packets_recv',
'errin', 'errout',
'dropin', 'dropout'])
# psutil.users()
suser = namedtuple('suser', ['name', 'terminal', 'host', 'started'])
# psutil.net_connections()
sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr',
'status', 'pid'])
class nt_connection(namedtuple('connection',
'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
# --- namedtuples for psutil.Process methods
@property
def remote_address(self):
warnings.warn("'remote_address' field is deprecated; use 'raddr'" \
"instead", category=DeprecationWarning, stacklevel=2)
return self.raddr
# psutil.Process.memory_info()
pmem = namedtuple('pmem', ['rss', 'vms'])
# psutil.Process.cpu_times()
pcputimes = namedtuple('pcputimes', ['user', 'system'])
# psutil.Process.open_files()
popenfile = namedtuple('popenfile', ['path', 'fd'])
# psutil.Process.threads()
pthread = namedtuple('pthread', ['id', 'user_time', 'system_time'])
# psutil.Process.uids()
puids = namedtuple('puids', ['real', 'effective', 'saved'])
# psutil.Process.gids()
pgids = namedtuple('pgids', ['real', 'effective', 'saved'])
# psutil.Process.io_counters()
pio = namedtuple('pio', ['read_count', 'write_count',
'read_bytes', 'write_bytes'])
# psutil.Process.ionice()
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

View File

@ -6,31 +6,43 @@
"""Module which provides compatibility with older Python versions."""
__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable",
"namedtuple", "property", "defaultdict"]
__all__ = ["PY3", "int", "long", "xrange", "exec_", "callable", "namedtuple",
"property", "wraps", "defaultdict", "update_wrapper", "lru_cache"]
import sys
# --- python 2/3 compatibility layer
PY3 = sys.version_info >= (3,)
try:
import __builtin__
except ImportError:
import builtins as __builtin__ # py3
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:
@ -51,16 +63,16 @@ else:
# removed in 3.0, reintroduced in 3.2
try:
callable = callable
except Exception:
except NameError:
def callable(obj):
for klass in type(obj).__mro__:
if "__call__" in klass.__dict__:
return True
return False
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
# --- 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:
@ -69,51 +81,45 @@ except ImportError:
import sys as _sys
def namedtuple(typename, field_names, verbose=False, rename=False):
"""A collections.namedtuple implementation written in Python
to support Python versions < 2.6.
Taken from: http://code.activestate.com/recipes/500261/
"""A collections.namedtuple implementation, see:
http://docs.python.org/library/collections.html#namedtuple
"""
# Parse and validate the field names. Validation serves two
# purposes, generating informative error messages and preventing
# template injection attacks.
if isinstance(field_names, basestring):
# names separated by whitespace and/or commas
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
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 ' \
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)
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)
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)
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)
# Create and fill-in the class template
numfields = len(field_names)
# tuple repr without parens or quotes
argtxt = repr(field_names).replace("'", "")[1:-1]
reprtxt = ', '.join('%s=%%r' % name for name in field_names)
template = '''class %(typename)s(tuple):
@ -127,7 +133,8 @@ except ImportError:
'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))
raise TypeError(
'Expected %(numfields)d arguments, got %%d' %% len(result))
return result \n
def __repr__(self):
return '%(typename)s(%(reprtxt)s)' %% self \n
@ -135,10 +142,10 @@ except ImportError:
'Return a new dict which maps field names to their values'
return dict(zip(self._fields, self)) \n
def _replace(_self, **kwds):
'Return a new %(typename)s object replacing specified fields with new values'
result = _self._make(map(kwds.pop, %(field_names)r, _self))
if kwds:
raise ValueError('Got unexpected field names: %%r' %% kwds.keys())
raise ValueError(
'Got unexpected field names: %%r' %% kwds.keys())
return result \n
def __getnewargs__(self):
return tuple(self) \n\n''' % locals()
@ -148,30 +155,25 @@ except ImportError:
sys.stdout.write(template + '\n')
sys.stdout.flush()
# Execute the template string in a temporary namespace
namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
_property=property, _tuple=tuple)
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]
# For pickling to work, the __module__ variable needs to be set
# to the frame where the named tuple is created. Bypass this
# step in enviroments where sys._getframe is not defined (Jython
# for example) or sys._getframe is not defined for arguments
# greater than 0 (IronPython).
try:
result.__module__ = _sys._getframe(1).f_globals.get('__name__', '__main__')
result.__module__ = _sys._getframe(
1).f_globals.get('__name__', '__main__')
except (AttributeError, ValueError):
pass
return result
# hack to support property.setter/deleter on python < 2.6
# 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
@ -196,15 +198,19 @@ else:
# py 2.5 collections.defauldict
# Taken from:
# http://code.activestate.com/recipes/523034-emulate-collectionsdefaultdict/
# credits: Jason Kirtland
# 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__')):
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
@ -250,15 +256,9 @@ try:
except ImportError:
def wraps(original):
def inner(fn):
# see functools.WRAPPER_ASSIGNMENTS
for attribute in ['__module__',
'__name__',
'__doc__'
]:
for attribute in ['__module__', '__name__', '__doc__']:
setattr(fn, attribute, getattr(original, attribute))
# see functools.WRAPPER_UPDATES
for attribute in ['__dict__',
]:
for attribute in ['__dict__']:
if hasattr(fn, attribute):
getattr(fn, attribute).update(getattr(original, attribute))
else:
@ -266,3 +266,170 @@ except ImportError:
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
# Credit: Raymond Hettinger
try:
from functools import lru_cache
except ImportError:
try:
from threading import RLock
except ImportError:
from dummy_threading import RLock
_CacheInfo = namedtuple("CacheInfo",
["hits", "misses", "maxsize", "currsize"])
class _HashedSeq(list):
__slots__ = 'hashvalue'
def __init__(self, tup, hash=hash):
self[:] = tup
self.hashvalue = hash(tup)
def __hash__(self):
return self.hashvalue
def _make_key(args, kwds, typed,
kwd_mark=(object(), ),
fasttypes=set((int, str, frozenset, type(None))),
sorted=sorted, tuple=tuple, type=type, len=len):
key = args
if kwds:
sorted_items = sorted(kwds.items())
key += kwd_mark
for item in sorted_items:
key += item
if typed:
key += tuple(type(v) for v in args)
if kwds:
key += tuple(type(v) for k, v in sorted_items)
elif len(key) == 1 and type(key[0]) in fasttypes:
return key[0]
return _HashedSeq(key)
def lru_cache(maxsize=100, typed=False):
"""Least-recently-used cache decorator, see:
http://docs.python.org/3/library/functools.html#functools.lru_cache
"""
def decorating_function(user_function):
cache = dict()
stats = [0, 0]
HITS, MISSES = 0, 1
make_key = _make_key
cache_get = cache.get
_len = len
lock = RLock()
root = []
root[:] = [root, root, None, None]
nonlocal_root = [root]
PREV, NEXT, KEY, RESULT = 0, 1, 2, 3
if maxsize == 0:
def wrapper(*args, **kwds):
result = user_function(*args, **kwds)
stats[MISSES] += 1
return result
elif maxsize is None:
def wrapper(*args, **kwds):
key = make_key(args, kwds, typed)
result = cache_get(key, root)
if result is not root:
stats[HITS] += 1
return result
result = user_function(*args, **kwds)
cache[key] = result
stats[MISSES] += 1
return result
else:
def wrapper(*args, **kwds):
if kwds or typed:
key = make_key(args, kwds, typed)
else:
key = args
lock.acquire()
try:
link = cache_get(key)
if link is not None:
root, = nonlocal_root
link_prev, link_next, key, result = link
link_prev[NEXT] = link_next
link_next[PREV] = link_prev
last = root[PREV]
last[NEXT] = root[PREV] = link
link[PREV] = last
link[NEXT] = root
stats[HITS] += 1
return result
finally:
lock.release()
result = user_function(*args, **kwds)
lock.acquire()
try:
root, = nonlocal_root
if key in cache:
pass
elif _len(cache) >= maxsize:
oldroot = root
oldroot[KEY] = key
oldroot[RESULT] = result
root = nonlocal_root[0] = oldroot[NEXT]
oldkey = root[KEY]
root[KEY] = root[RESULT] = None
del cache[oldkey]
cache[key] = oldroot
else:
last = root[PREV]
link = [last, root, key, result]
last[NEXT] = root[PREV] = cache[key] = link
stats[MISSES] += 1
finally:
lock.release()
return result
def cache_info():
"""Report cache statistics"""
lock.acquire()
try:
return _CacheInfo(stats[HITS], stats[MISSES], maxsize,
len(cache))
finally:
lock.release()
def cache_clear():
"""Clear the cache and cache statistics"""
lock.acquire()
try:
cache.clear()
root = nonlocal_root[0]
root[:] = [root, root, None, None]
stats[:] = [0, 0]
finally:
lock.release()
wrapper.__wrapped__ = user_function
wrapper.cache_info = cache_info
wrapper.cache_clear = cache_clear
return update_wrapper(wrapper, user_function)
return decorating_function

View File

@ -1,73 +0,0 @@
#!/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.
"""psutil exception classes.
Not supposed to be used / imported directly.
Instead use psutil.NoSuchProcess, etc.
"""
class Error(Exception):
"""Base exception class. All other psutil exceptions inherit
from this one.
"""
class NoSuchProcess(Error):
"""Exception raised when a process with a certain PID doesn't
or no longer exists (zombie).
"""
def __init__(self, pid, name=None, msg=None):
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if name:
details = "(pid=%s, name=%s)" % (self.pid, repr(self.name))
else:
details = "(pid=%s)" % self.pid
self.msg = "process no longer exists " + details
def __str__(self):
return self.msg
class AccessDenied(Error):
"""Exception raised when permission to perform an action is denied."""
def __init__(self, pid=None, name=None, msg=None):
self.pid = pid
self.name = name
self.msg = msg
if msg is None:
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
def __str__(self):
return self.msg
class TimeoutExpired(Error):
"""Raised on Process.wait(timeout) if timeout expires and process
is still alive.
"""
def __init__(self, pid=None, name=None):
self.pid = pid
self.name = name
if (pid is not None) and (name is not None):
self.msg = "(pid=%s, name=%s)" % (pid, repr(name))
elif (pid is not None):
self.msg = "(pid=%s)" % self.pid
else:
self.msg = ""
def __str__(self):
return self.msg

View File

@ -9,137 +9,197 @@
import errno
import os
import sys
import warnings
import _psutil_bsd
import _psutil_posix
from psutil import _common
from psutil import _psposix
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
from psutil._common import conn_tmap, usage_percent
from psutil._compat import namedtuple, wraps
from psutil._common import *
import _psutil_bsd as cext
import _psutil_posix
__extra__all__ = []
# --- constants
# Since these constants get determined at import time we do not want to
# crash immediately; instead we'll set them to None and most likely
# we'll crash later as they're used for determining process CPU stats
# and creation_time
try:
NUM_CPUS = _psutil_bsd.get_num_cpus()
except Exception:
NUM_CPUS = None
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
try:
TOTAL_PHYMEM = _psutil_bsd.get_virtual_mem()[0]
except Exception:
TOTAL_PHYMEM = None
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
try:
BOOT_TIME = _psutil_bsd.get_system_boot_time()
except Exception:
BOOT_TIME = None
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
PROC_STATUSES = {
cext.SSTOP: _common.STATUS_STOPPED,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SRUN: _common.STATUS_RUNNING,
cext.SIDL: _common.STATUS_IDLE,
cext.SWAIT: _common.STATUS_WAITING,
cext.SLOCK: _common.STATUS_LOCKED,
cext.SZOMB: _common.STATUS_ZOMBIE,
}
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
cext.TCPS_CLOSED: _common.CONN_CLOSE,
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
cext.TCPS_LISTEN: _common.CONN_LISTEN,
cext.TCPS_CLOSING: _common.CONN_CLOSING,
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
_cputimes_ntuple = namedtuple('cputimes', 'user nice system idle irq')
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
# --- public functions
# extend base mem ntuple with BSD-specific memory metrics
svmem = namedtuple(
'svmem', ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'buffers', 'cached', 'shared', 'wired'])
scputimes = namedtuple(
'scputimes', ['user', 'nice', 'system', 'idle', 'irq'])
pextmem = namedtuple('pextmem', ['rss', 'vms', 'text', 'data', 'stack'])
pmmap_grouped = namedtuple(
'pmmap_grouped', 'path rss, private, ref_count, shadow_count')
pmmap_ext = namedtuple(
'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count')
get_system_boot_time = _psutil_bsd.get_system_boot_time
# set later from __init__.py
NoSuchProcess = None
AccessDenied = None
TimeoutExpired = None
nt_virtmem_info = namedtuple('vmem', ' '.join([
# all platforms
'total', 'available', 'percent', 'used', 'free',
# FreeBSD specific
'active',
'inactive',
'buffers',
'cached',
'shared',
'wired']))
def virtual_memory():
"""System virtual memory as a namedutple."""
mem = _psutil_bsd.get_virtual_mem()
mem = cext.virtual_mem()
total, free, active, inactive, wired, cached, buffers, shared = mem
avail = inactive + cached + free
used = active + wired + cached
used = active + wired + cached
percent = usage_percent((total - avail), total, _round=1)
return nt_virtmem_info(total, avail, percent, used, free,
active, inactive, buffers, cached, shared, wired)
return svmem(total, avail, percent, used, free,
active, inactive, buffers, cached, shared, wired)
def swap_memory():
"""System swap memory as (total, used, free, sin, sout) namedtuple."""
total, used, free, sin, sout = \
[x * _PAGESIZE for x in _psutil_bsd.get_swap_mem()]
total, used, free, sin, sout = [x * PAGESIZE for x in cext.swap_mem()]
percent = usage_percent(used, total, _round=1)
return nt_swapmeminfo(total, used, free, percent, sin, sout)
return _common.sswap(total, used, free, percent, sin, sout)
def get_system_cpu_times():
def cpu_times():
"""Return system per-CPU times as a named tuple"""
user, nice, system, idle, irq = _psutil_bsd.get_system_cpu_times()
return _cputimes_ntuple(user, nice, system, idle, irq)
user, nice, system, idle, irq = cext.cpu_times()
return scputimes(user, nice, system, idle, irq)
def get_system_per_cpu_times():
"""Return system CPU times as a named tuple"""
ret = []
for cpu_t in _psutil_bsd.get_system_per_cpu_times():
user, nice, system, idle, irq = cpu_t
item = _cputimes_ntuple(user, nice, system, idle, irq)
ret.append(item)
return ret
# XXX
# Ok, this is very dirty.
# On FreeBSD < 8 we cannot gather per-cpu information, see:
# http://code.google.com/p/psutil/issues/detail?id=226
# If NUM_CPUS > 1, on first call we return single cpu times to avoid a
# crash at psutil import time.
# Next calls will fail with NotImplementedError
if not hasattr(_psutil_bsd, "get_system_per_cpu_times"):
def get_system_per_cpu_times():
if NUM_CPUS == 1:
return [get_system_cpu_times]
if get_system_per_cpu_times.__called__:
if hasattr(cext, "per_cpu_times"):
def per_cpu_times():
"""Return system CPU times as a named tuple"""
ret = []
for cpu_t in cext.per_cpu_times():
user, nice, system, idle, irq = cpu_t
item = scputimes(user, nice, system, idle, irq)
ret.append(item)
return ret
else:
# XXX
# Ok, this is very dirty.
# On FreeBSD < 8 we cannot gather per-cpu information, see:
# https://github.com/giampaolo/psutil/issues/226
# If num cpus > 1, on first call we return single cpu times to avoid a
# crash at psutil import time.
# Next calls will fail with NotImplementedError
def per_cpu_times():
if cpu_count_logical() == 1:
return [cpu_times()]
if per_cpu_times.__called__:
raise NotImplementedError("supported only starting from FreeBSD 8")
get_system_per_cpu_times.__called__ = True
return [get_system_cpu_times]
get_system_per_cpu_times.__called__ = False
per_cpu_times.__called__ = True
return [cpu_times()]
per_cpu_times.__called__ = False
def cpu_count_logical():
"""Return the number of logical CPUs in the system."""
return cext.cpu_count_logical()
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
# From the C module we'll get an XML string similar to this:
# http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html
# 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.
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
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def disk_partitions(all=False):
retlist = []
partitions = _psutil_bsd.get_disk_partitions()
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
if device == 'none':
device = ''
if not all:
if not os.path.isabs(device) \
or not os.path.exists(device):
if not os.path.isabs(device) or not os.path.exists(device):
continue
ntuple = nt_partition(device, mountpoint, fstype, opts)
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
def get_system_users():
def users():
retlist = []
rawlist = _psutil_bsd.get_system_users()
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp = item
if tty == '~':
continue # reboot or shutdown
nt = nt_user(user, tty or None, hostname, tstamp)
nt = _common.suser(user, tty or None, hostname, tstamp)
retlist.append(nt)
return retlist
get_pid_list = _psutil_bsd.get_pid_list
def net_connections(kind):
if kind not in _common.conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
ret = []
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]
nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid)
ret.append(nt)
return ret
pids = cext.pids
pid_exists = _psposix.pid_exists
get_disk_usage = _psposix.get_disk_usage
net_io_counters = _psutil_bsd.get_net_io_counters
disk_io_counters = _psutil_bsd.get_disk_io_counters
disk_usage = _psposix.disk_usage
net_io_counters = cext.net_io_counters
disk_io_counters = cext.disk_io_counters
def wrap_exceptions(fun):
@ -151,66 +211,42 @@ def wrap_exceptions(fun):
try:
return fun(self, *args, **kwargs)
except OSError:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._process_name)
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
raise
return wrapper
_status_map = {
_psutil_bsd.SSTOP : STATUS_STOPPED,
_psutil_bsd.SSLEEP : STATUS_SLEEPING,
_psutil_bsd.SRUN : STATUS_RUNNING,
_psutil_bsd.SIDL : STATUS_IDLE,
_psutil_bsd.SWAIT : STATUS_WAITING,
_psutil_bsd.SLOCK : STATUS_LOCKED,
_psutil_bsd.SZOMB : STATUS_ZOMBIE,
}
_conn_status_map = {_psutil_bsd.TCPS_ESTABLISHED : CONN_ESTABLISHED,
_psutil_bsd.TCPS_SYN_SENT : CONN_SYN_SENT,
_psutil_bsd.TCPS_SYN_RECEIVED : CONN_SYN_RECV,
_psutil_bsd.TCPS_FIN_WAIT_1 : CONN_FIN_WAIT1,
_psutil_bsd.TCPS_FIN_WAIT_2 : CONN_FIN_WAIT2,
_psutil_bsd.TCPS_TIME_WAIT : CONN_TIME_WAIT,
_psutil_bsd.TCPS_CLOSED : CONN_CLOSE,
_psutil_bsd.TCPS_CLOSE_WAIT : CONN_CLOSE_WAIT,
_psutil_bsd.TCPS_LAST_ACK : CONN_LAST_ACK,
_psutil_bsd.TCPS_LISTEN : CONN_LISTEN,
_psutil_bsd.TCPS_CLOSING : CONN_CLOSING,
_psutil_bsd.PSUTIL_CONN_NONE : CONN_NONE,
}
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_process_name"]
__slots__ = ["pid", "_name"]
def __init__(self, pid):
self.pid = pid
self._process_name = None
self._name = None
@wrap_exceptions
def get_process_name(self):
"""Return process name as a string of limited len (15)."""
return _psutil_bsd.get_process_name(self.pid)
def name(self):
return cext.proc_name(self.pid)
@wrap_exceptions
def get_process_exe(self):
"""Return process executable pathname."""
return _psutil_bsd.get_process_exe(self.pid)
def exe(self):
return cext.proc_exe(self.pid)
@wrap_exceptions
def get_process_cmdline(self):
"""Return process cmdline as a list of arguments."""
return _psutil_bsd.get_process_cmdline(self.pid)
def cmdline(self):
return cext.proc_cmdline(self.pid)
@wrap_exceptions
def get_process_terminal(self):
tty_nr = _psutil_bsd.get_process_tty_nr(self.pid)
def terminal(self):
tty_nr = cext.proc_tty_nr(self.pid)
tmap = _psposix._get_terminal_map()
try:
return tmap[tty_nr]
@ -218,150 +254,136 @@ class Process(object):
return None
@wrap_exceptions
def get_process_ppid(self):
"""Return process parent pid."""
return _psutil_bsd.get_process_ppid(self.pid)
# XXX - available on FreeBSD >= 8 only
if hasattr(_psutil_bsd, "get_process_cwd"):
@wrap_exceptions
def get_process_cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
return _psutil_bsd.get_process_cwd(self.pid) or None
def ppid(self):
return cext.proc_ppid(self.pid)
@wrap_exceptions
def get_process_uids(self):
"""Return real, effective and saved user ids."""
real, effective, saved = _psutil_bsd.get_process_uids(self.pid)
return nt_uids(real, effective, saved)
def uids(self):
real, effective, saved = cext.proc_uids(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def get_process_gids(self):
"""Return real, effective and saved group ids."""
real, effective, saved = _psutil_bsd.get_process_gids(self.pid)
return nt_gids(real, effective, saved)
def gids(self):
real, effective, saved = cext.proc_gids(self.pid)
return _common.pgids(real, effective, saved)
@wrap_exceptions
def get_cpu_times(self):
"""return a tuple containing process user/kernel time."""
user, system = _psutil_bsd.get_process_cpu_times(self.pid)
return nt_cputimes(user, system)
def cpu_times(self):
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def get_memory_info(self):
"""Return a tuple with the process' RSS and VMS size."""
rss, vms = _psutil_bsd.get_process_memory_info(self.pid)[:2]
return nt_meminfo(rss, vms)
_nt_ext_mem = namedtuple('meminfo', 'rss vms text data stack')
def memory_info(self):
rss, vms = cext.proc_memory_info(self.pid)[:2]
return _common.pmem(rss, vms)
@wrap_exceptions
def get_ext_memory_info(self):
return self._nt_ext_mem(*_psutil_bsd.get_process_memory_info(self.pid))
def memory_info_ex(self):
return pextmem(*cext.proc_memory_info(self.pid))
@wrap_exceptions
def get_process_create_time(self):
"""Return the start time of the process as a number of seconds since
the epoch."""
return _psutil_bsd.get_process_create_time(self.pid)
def create_time(self):
return cext.proc_create_time(self.pid)
@wrap_exceptions
def get_process_num_threads(self):
"""Return the number of threads belonging to the process."""
return _psutil_bsd.get_process_num_threads(self.pid)
def num_threads(self):
return cext.proc_num_threads(self.pid)
@wrap_exceptions
def get_num_ctx_switches(self):
return nt_ctxsw(*_psutil_bsd.get_process_num_ctx_switches(self.pid))
def num_ctx_switches(self):
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def get_num_fds(self):
"""Return the number of file descriptors opened by this process."""
return _psutil_bsd.get_process_num_fds(self.pid)
@wrap_exceptions
def get_process_threads(self):
"""Return the number of threads belonging to the process."""
rawlist = _psutil_bsd.get_process_threads(self.pid)
def threads(self):
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = nt_thread(thread_id, utime, stime)
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def get_open_files(self):
"""Return files opened by process as a list of namedtuples."""
# XXX - C implementation available on FreeBSD >= 8 only
# else fallback on lsof parser
if hasattr(_psutil_bsd, "get_process_open_files"):
rawlist = _psutil_bsd.get_process_open_files(self.pid)
return [nt_openfile(path, fd) for path, fd in rawlist]
else:
lsof = _psposix.LsofParser(self.pid, self._process_name)
return lsof.get_process_open_files()
@wrap_exceptions
def get_connections(self, kind='inet'):
"""Return etwork connections opened by a process as a list of
namedtuples.
"""
def connections(self, kind='inet'):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = _psutil_bsd.get_process_connections(self.pid, families, types)
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
status = _conn_status_map[status]
nt = nt_connection(fd, fam, type, laddr, raddr, status)
status = TCP_STATUSES[status]
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.append(nt)
return ret
@wrap_exceptions
def process_wait(self, timeout=None):
def wait(self, timeout=None):
try:
return _psposix.wait_pid(self.pid, timeout)
except TimeoutExpired:
raise TimeoutExpired(self.pid, self._process_name)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)
@wrap_exceptions
def get_process_nice(self):
def nice_get(self):
return _psutil_posix.getpriority(self.pid)
@wrap_exceptions
def set_process_nice(self, value):
def nice_set(self, value):
return _psutil_posix.setpriority(self.pid, value)
@wrap_exceptions
def get_process_status(self):
code = _psutil_bsd.get_process_status(self.pid)
if code in _status_map:
return _status_map[code]
return constant(-1, "?")
def status(self):
code = cext.proc_status(self.pid)
if code in PROC_STATUSES:
return PROC_STATUSES[code]
# XXX is this legit? will we even ever get here?
return "?"
@wrap_exceptions
def get_process_io_counters(self):
rc, wc, rb, wb = _psutil_bsd.get_process_io_counters(self.pid)
return nt_io(rc, wc, rb, wb)
def io_counters(self):
rc, wc, rb, wb = cext.proc_io_counters(self.pid)
return _common.pio(rc, wc, rb, wb)
nt_mmap_grouped = namedtuple('mmap',
'path rss, private, ref_count, shadow_count')
nt_mmap_ext = namedtuple('mmap',
'addr, perms path rss, private, ref_count, shadow_count')
nt_mmap_grouped = namedtuple(
'mmap', 'path rss, private, ref_count, shadow_count')
nt_mmap_ext = namedtuple(
'mmap', 'addr, perms path rss, private, ref_count, shadow_count')
@wrap_exceptions
def get_memory_maps(self):
return _psutil_bsd.get_process_memory_maps(self.pid)
# FreeBSD < 8 does not support functions based on kinfo_getfile()
# and kinfo_getvmmap()
if hasattr(cext, 'proc_open_files'):
# FreeBSD < 8 does not support kinfo_getfile() and kinfo_getvmmap()
if not hasattr(_psutil_bsd, 'get_process_open_files'):
@wrap_exceptions
def open_files(self):
"""Return files opened by process as a list of namedtuples."""
rawlist = cext.proc_open_files(self.pid)
return [_common.popenfile(path, fd) for path, fd in rawlist]
@wrap_exceptions
def cwd(self):
"""Return process current working directory."""
# sometimes we get an empty string, in which case we turn
# it into None
return cext.proc_cwd(self.pid) or None
@wrap_exceptions
def memory_maps(self):
return cext.proc_memory_maps(self.pid)
@wrap_exceptions
def num_fds(self):
"""Return the number of file descriptors opened by this process."""
return cext.proc_num_fds(self.pid)
else:
def _not_implemented(self):
raise NotImplementedError("supported only starting from FreeBSD 8")
get_open_files = _not_implemented
get_process_cwd = _not_implemented
get_memory_maps = _not_implemented
get_num_fds = _not_implemented
open_files = _not_implemented
proc_cwd = _not_implemented
memory_maps = _not_implemented
num_fds = _not_implemented

File diff suppressed because it is too large Load Diff

View File

@ -1,482 +0,0 @@
#!/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.
"""Windows platform implementation."""
import errno
import os
import sys
import platform
import warnings
import _psutil_mswindows
from _psutil_mswindows import ERROR_ACCESS_DENIED
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
from psutil._common import *
from psutil._compat import PY3, xrange, long, wraps
# Windows specific extended namespace
__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",
]
# --- module level constants (gets pushed up to psutil module)
# Since these constants get determined at import time we do not want to
# crash immediately; instead we'll set them to None and most likely
# we'll crash later as they're used for determining process CPU stats
# and creation_time
try:
NUM_CPUS = _psutil_mswindows.get_num_cpus()
except Exception:
NUM_CPUS = None
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
try:
BOOT_TIME = _psutil_mswindows.get_system_boot_time()
except Exception:
BOOT_TIME = None
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
try:
TOTAL_PHYMEM = _psutil_mswindows.get_virtual_mem()[0]
except Exception:
TOTAL_PHYMEM = None
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
CONN_DELETE_TCB = constant(11, "DELETE_TCB")
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED])
TCP_STATES_TABLE = {
_psutil_mswindows.MIB_TCP_STATE_ESTAB : CONN_ESTABLISHED,
_psutil_mswindows.MIB_TCP_STATE_SYN_SENT : CONN_SYN_SENT,
_psutil_mswindows.MIB_TCP_STATE_SYN_RCVD : CONN_SYN_RECV,
_psutil_mswindows.MIB_TCP_STATE_FIN_WAIT1 : CONN_FIN_WAIT1,
_psutil_mswindows.MIB_TCP_STATE_FIN_WAIT2 : CONN_FIN_WAIT2,
_psutil_mswindows.MIB_TCP_STATE_TIME_WAIT : CONN_TIME_WAIT,
_psutil_mswindows.MIB_TCP_STATE_CLOSED : CONN_CLOSE,
_psutil_mswindows.MIB_TCP_STATE_CLOSE_WAIT : CONN_CLOSE_WAIT,
_psutil_mswindows.MIB_TCP_STATE_LAST_ACK : CONN_LAST_ACK,
_psutil_mswindows.MIB_TCP_STATE_LISTEN : CONN_LISTEN,
_psutil_mswindows.MIB_TCP_STATE_CLOSING : CONN_CLOSING,
_psutil_mswindows.MIB_TCP_STATE_DELETE_TCB : CONN_DELETE_TCB,
_psutil_mswindows.PSUTIL_CONN_NONE : CONN_NONE,
}
# process priority constants:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
from _psutil_mswindows import (ABOVE_NORMAL_PRIORITY_CLASS,
BELOW_NORMAL_PRIORITY_CLASS,
HIGH_PRIORITY_CLASS,
IDLE_PRIORITY_CLASS,
NORMAL_PRIORITY_CLASS,
REALTIME_PRIORITY_CLASS,
INFINITE)
@memoize
def _win32_QueryDosDevice(s):
return _psutil_mswindows.win32_QueryDosDevice(s)
def _convert_raw_path(s):
# convert paths using native DOS format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# into: "C:\Windows\systemew\file.txt"
if PY3 and not isinstance(s, str):
s = s.decode('utf8')
rawdrive = '\\'.join(s.split('\\')[:3])
driveletter = _win32_QueryDosDevice(rawdrive)
return os.path.join(driveletter, s[len(rawdrive):])
# --- public functions
get_system_boot_time = _psutil_mswindows.get_system_boot_time
nt_virtmem_info = namedtuple('vmem', ' '.join([
# all platforms
'total', 'available', 'percent', 'used', 'free']))
def virtual_memory():
"""System virtual memory as a namedtuple."""
mem = _psutil_mswindows.get_virtual_mem()
totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem
#
total = totphys
avail = availphys
free = availphys
used = total - avail
percent = usage_percent((total - avail), total, _round=1)
return nt_virtmem_info(total, avail, percent, used, free)
def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
mem = _psutil_mswindows.get_virtual_mem()
total = mem[2]
free = mem[3]
used = total - free
percent = usage_percent(used, total, _round=1)
return nt_swapmeminfo(total, used, free, percent, 0, 0)
def get_disk_usage(path):
"""Return disk usage associated with path."""
try:
total, free = _psutil_mswindows.get_disk_usage(path)
except WindowsError:
err = sys.exc_info()[1]
if not os.path.exists(path):
raise OSError(errno.ENOENT, "No such file or directory: '%s'" % path)
raise
used = total - free
percent = usage_percent(used, total, _round=1)
return nt_diskinfo(total, used, free, percent)
def disk_partitions(all):
"""Return disk partitions."""
rawlist = _psutil_mswindows.get_disk_partitions(all)
return [nt_partition(*x) for x in rawlist]
_cputimes_ntuple = namedtuple('cputimes', 'user system idle')
def get_system_cpu_times():
"""Return system CPU times as a named tuple."""
user, system, idle = 0, 0, 0
# computes system global times summing each processor value
for cpu_time in _psutil_mswindows.get_system_cpu_times():
user += cpu_time[0]
system += cpu_time[1]
idle += cpu_time[2]
return _cputimes_ntuple(user, system, idle)
def get_system_per_cpu_times():
"""Return system per-CPU times as a list of named tuples."""
ret = []
for cpu_t in _psutil_mswindows.get_system_cpu_times():
user, system, idle = cpu_t
item = _cputimes_ntuple(user, system, idle)
ret.append(item)
return ret
def get_system_users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = _psutil_mswindows.get_system_users()
for item in rawlist:
user, hostname, tstamp = item
nt = nt_user(user, None, hostname, tstamp)
retlist.append(nt)
return retlist
get_pid_list = _psutil_mswindows.get_pid_list
pid_exists = _psutil_mswindows.pid_exists
net_io_counters = _psutil_mswindows.get_net_io_counters
disk_io_counters = _psutil_mswindows.get_disk_io_counters
# --- decorator
def wrap_exceptions(fun):
"""Decorator which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
@wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise AccessDenied(self.pid, self._process_name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._process_name)
raise
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_process_name"]
def __init__(self, pid):
self.pid = pid
self._process_name = None
@wrap_exceptions
def get_process_name(self):
"""Return process name as a string of limited len (15)."""
return _psutil_mswindows.get_process_name(self.pid)
@wrap_exceptions
def get_process_exe(self):
# Note: os.path.exists(path) may return False even if the file
# is there, see:
# http://stackoverflow.com/questions/3112546/os-path-exists-lies
return _convert_raw_path(_psutil_mswindows.get_process_exe(self.pid))
@wrap_exceptions
def get_process_cmdline(self):
"""Return process cmdline as a list of arguments."""
return _psutil_mswindows.get_process_cmdline(self.pid)
@wrap_exceptions
def get_process_ppid(self):
"""Return process parent pid."""
return _psutil_mswindows.get_process_ppid(self.pid)
def _get_raw_meminfo(self):
try:
return _psutil_mswindows.get_process_memory_info(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return _psutil_mswindows.get_process_memory_info_2(self.pid)
raise
@wrap_exceptions
def get_memory_info(self):
"""Returns a tuple or RSS/VMS memory usage in bytes."""
# on Windows RSS == WorkingSetSize and VSM == PagefileUsage
# fields of PROCESS_MEMORY_COUNTERS struct:
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms684877(v=vs.85).aspx
t = self._get_raw_meminfo()
return nt_meminfo(t[2], t[7])
_nt_ext_mem = namedtuple('meminfo',
' '.join(['num_page_faults',
'peak_wset',
'wset',
'peak_paged_pool',
'paged_pool',
'peak_nonpaged_pool',
'nonpaged_pool',
'pagefile',
'peak_pagefile',
'private',]))
@wrap_exceptions
def get_ext_memory_info(self):
return self._nt_ext_mem(*self._get_raw_meminfo())
nt_mmap_grouped = namedtuple('mmap', 'path rss')
nt_mmap_ext = namedtuple('mmap', 'addr perms path rss')
def get_memory_maps(self):
try:
raw = _psutil_mswindows.get_process_memory_maps(self.pid)
except OSError:
# 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 (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED):
raise AccessDenied(self.pid, self._process_name)
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._process_name)
raise
else:
for addr, perm, path, rss in raw:
path = _convert_raw_path(path)
addr = hex(addr)
yield (addr, perm, path, rss)
@wrap_exceptions
def kill_process(self):
"""Terminates the process with the given PID."""
return _psutil_mswindows.kill_process(self.pid)
@wrap_exceptions
def process_wait(self, timeout=None):
if timeout is None:
timeout = INFINITE
else:
# WaitForSingleObject() expects time in milliseconds
timeout = int(timeout * 1000)
ret = _psutil_mswindows.process_wait(self.pid, timeout)
if ret == WAIT_TIMEOUT:
raise TimeoutExpired(self.pid, self._process_name)
return ret
@wrap_exceptions
def get_process_username(self):
"""Return the name of the user that owns the process"""
if self.pid in (0, 4):
return 'NT AUTHORITY\\SYSTEM'
return _psutil_mswindows.get_process_username(self.pid)
@wrap_exceptions
def get_process_create_time(self):
# special case for kernel process PIDs; return system boot time
if self.pid in (0, 4):
return BOOT_TIME
try:
return _psutil_mswindows.get_process_create_time(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return _psutil_mswindows.get_process_create_time_2(self.pid)
raise
@wrap_exceptions
def get_process_num_threads(self):
return _psutil_mswindows.get_process_num_threads(self.pid)
@wrap_exceptions
def get_process_threads(self):
rawlist = _psutil_mswindows.get_process_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = nt_thread(thread_id, utime, stime)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def get_cpu_times(self):
try:
ret = _psutil_mswindows.get_process_cpu_times(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
ret = _psutil_mswindows.get_process_cpu_times_2(self.pid)
else:
raise
return nt_cputimes(*ret)
@wrap_exceptions
def suspend_process(self):
return _psutil_mswindows.suspend_process(self.pid)
@wrap_exceptions
def resume_process(self):
return _psutil_mswindows.resume_process(self.pid)
@wrap_exceptions
def get_process_cwd(self):
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._process_name)
# return a normalized pathname since the native C function appends
# "\\" at the and of the path
path = _psutil_mswindows.get_process_cwd(self.pid)
return os.path.normpath(path)
@wrap_exceptions
def get_open_files(self):
if self.pid in (0, 4):
return []
retlist = []
# Filenames come in in native format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# Convert the first part in the corresponding drive letter
# (e.g. "C:\") by using Windows's QueryDosDevice()
raw_file_names = _psutil_mswindows.get_process_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 = nt_openfile(file, -1)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def get_connections(self, kind='inet'):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = _psutil_mswindows.get_process_connections(self.pid, families,
types)
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
status = TCP_STATES_TABLE[status]
nt = nt_connection(fd, fam, type, laddr, raddr, status)
ret.append(nt)
return ret
@wrap_exceptions
def get_process_nice(self):
return _psutil_mswindows.get_process_priority(self.pid)
@wrap_exceptions
def set_process_nice(self, value):
return _psutil_mswindows.set_process_priority(self.pid, value)
# available on Windows >= Vista
if hasattr(_psutil_mswindows, "get_process_io_priority"):
@wrap_exceptions
def get_process_ionice(self):
return _psutil_mswindows.get_process_io_priority(self.pid)
@wrap_exceptions
def set_process_ionice(self, value, _):
if _:
raise TypeError("set_process_ionice() on Windows takes only " \
"1 argument (2 given)")
if value not in (2, 1, 0):
raise ValueError("value must be 2 (normal), 1 (low) or 0 " \
"(very low); got %r" % value)
return _psutil_mswindows.set_process_io_priority(self.pid, value)
@wrap_exceptions
def get_process_io_counters(self):
try:
ret = _psutil_mswindows.get_process_io_counters(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
ret = _psutil_mswindows.get_process_io_counters_2(self.pid)
else:
raise
return nt_io(*ret)
@wrap_exceptions
def get_process_status(self):
suspended = _psutil_mswindows.is_process_suspended(self.pid)
if suspended:
return STATUS_STOPPED
else:
return STATUS_RUNNING
@wrap_exceptions
def get_process_cpu_affinity(self):
from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x]
bitmask = _psutil_mswindows.get_process_cpu_affinity(self.pid)
return from_bitmask(bitmask)
@wrap_exceptions
def set_process_cpu_affinity(self, value):
def to_bitmask(l):
if not l:
raise ValueError("invalid argument %r" % l)
out = 0
for b in l:
out |= 2**b
return out
# SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER
# is returned for an invalid CPU but this seems not to be true,
# therefore we check CPUs validy beforehand.
allcpus = list(range(len(get_system_per_cpu_times())))
for cpu in value:
if cpu not in allcpus:
raise ValueError("invalid CPU %r" % cpu)
bitmask = to_bitmask(value)
_psutil_mswindows.set_process_cpu_affinity(self.pid, bitmask)
@wrap_exceptions
def get_num_handles(self):
try:
return _psutil_mswindows.get_process_num_handles(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return _psutil_mswindows.get_process_num_handles_2(self.pid)
raise
@wrap_exceptions
def get_num_ctx_switches(self):
return nt_ctxsw(*_psutil_mswindows.get_process_num_ctx_switches(self.pid))

View File

@ -9,133 +9,168 @@
import errno
import os
import sys
import warnings
import _psutil_osx
import _psutil_posix
from psutil import _common
from psutil import _psposix
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
from psutil._common import conn_tmap, usage_percent, isfile_strict
from psutil._compat import namedtuple, wraps
from psutil._common import *
import _psutil_osx as cext
import _psutil_posix
__extra__all__ = []
# --- constants
# Since these constants get determined at import time we do not want to
# crash immediately; instead we'll set them to None and most likely
# we'll crash later as they're used for determining process CPU stats
# and creation_time
try:
NUM_CPUS = _psutil_osx.get_num_cpus()
except Exception:
NUM_CPUS = None
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
try:
BOOT_TIME = _psutil_osx.get_system_boot_time()
except Exception:
BOOT_TIME = None
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
try:
TOTAL_PHYMEM = _psutil_osx.get_virtual_mem()[0]
except Exception:
TOTAL_PHYMEM = None
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
_cputimes_ntuple = namedtuple('cputimes', 'user nice system idle')
# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
_TCP_STATES_TABLE = {_psutil_osx.TCPS_ESTABLISHED : CONN_ESTABLISHED,
_psutil_osx.TCPS_SYN_SENT : CONN_SYN_SENT,
_psutil_osx.TCPS_SYN_RECEIVED : CONN_SYN_RECV,
_psutil_osx.TCPS_FIN_WAIT_1 : CONN_FIN_WAIT1,
_psutil_osx.TCPS_FIN_WAIT_2 : CONN_FIN_WAIT2,
_psutil_osx.TCPS_TIME_WAIT : CONN_TIME_WAIT,
_psutil_osx.TCPS_CLOSED : CONN_CLOSE,
_psutil_osx.TCPS_CLOSE_WAIT : CONN_CLOSE_WAIT,
_psutil_osx.TCPS_LAST_ACK : CONN_LAST_ACK,
_psutil_osx.TCPS_LISTEN : CONN_LISTEN,
_psutil_osx.TCPS_CLOSING : CONN_CLOSING,
_psutil_osx.PSUTIL_CONN_NONE : CONN_NONE,
}
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV,
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
cext.TCPS_CLOSED: _common.CONN_CLOSE,
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
cext.TCPS_LISTEN: _common.CONN_LISTEN,
cext.TCPS_CLOSING: _common.CONN_CLOSING,
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
PROC_STATUSES = {
cext.SIDL: _common.STATUS_IDLE,
cext.SRUN: _common.STATUS_RUNNING,
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SSTOP: _common.STATUS_STOPPED,
cext.SZOMB: _common.STATUS_ZOMBIE,
}
scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle'])
svmem = namedtuple(
'svmem', ['total', 'available', 'percent', 'used', 'free',
'active', 'inactive', 'wired'])
pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins'])
pmmap_grouped = namedtuple(
'pmmap_grouped',
'path rss private swapped dirtied ref_count shadow_depth')
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# set later from __init__.py
NoSuchProcess = None
AccessDenied = None
TimeoutExpired = None
# --- functions
get_system_boot_time = _psutil_osx.get_system_boot_time
nt_virtmem_info = namedtuple('vmem', ' '.join([
# all platforms
'total', 'available', 'percent', 'used', 'free',
# OSX specific
'active',
'inactive',
'wired']))
def virtual_memory():
"""System virtual memory as a namedtuple."""
total, active, inactive, wired, free = _psutil_osx.get_virtual_mem()
total, active, inactive, wired, free = cext.virtual_mem()
avail = inactive + free
used = active + inactive + wired
percent = usage_percent((total - avail), total, _round=1)
return nt_virtmem_info(total, avail, percent, used, free,
active, inactive, wired)
return svmem(total, avail, percent, used, free,
active, inactive, wired)
def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
total, used, free, sin, sout = _psutil_osx.get_swap_mem()
total, used, free, sin, sout = cext.swap_mem()
percent = usage_percent(used, total, _round=1)
return nt_swapmeminfo(total, used, free, percent, sin, sout)
return _common.sswap(total, used, free, percent, sin, sout)
def get_system_cpu_times():
def cpu_times():
"""Return system CPU times as a namedtuple."""
user, nice, system, idle = _psutil_osx.get_system_cpu_times()
return _cputimes_ntuple(user, nice, system, idle)
user, nice, system, idle = cext.cpu_times()
return scputimes(user, nice, system, idle)
def get_system_per_cpu_times():
def per_cpu_times():
"""Return system CPU times as a named tuple"""
ret = []
for cpu_t in _psutil_osx.get_system_per_cpu_times():
for cpu_t in cext.per_cpu_times():
user, nice, system, idle = cpu_t
item = _cputimes_ntuple(user, nice, system, idle)
item = scputimes(user, nice, system, idle)
ret.append(item)
return ret
def cpu_count_logical():
"""Return the number of logical CPUs in the system."""
return cext.cpu_count_logical()
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
return cext.cpu_count_phys()
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def disk_partitions(all=False):
retlist = []
partitions = _psutil_osx.get_disk_partitions()
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
if device == 'none':
device = ''
if not all:
if not os.path.isabs(device) \
or not os.path.exists(device):
if not os.path.isabs(device) or not os.path.exists(device):
continue
ntuple = nt_partition(device, mountpoint, fstype, opts)
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
def get_system_users():
def users():
retlist = []
rawlist = _psutil_osx.get_system_users()
rawlist = cext.users()
for item in rawlist:
user, tty, hostname, tstamp = item
if tty == '~':
continue # reboot or shutdown
if not tstamp:
continue
nt = nt_user(user, tty or None, hostname or None, tstamp)
nt = _common.suser(user, tty or None, hostname or None, tstamp)
retlist.append(nt)
return retlist
get_pid_list = _psutil_osx.get_pid_list
pid_exists = _psposix.pid_exists
get_disk_usage = _psposix.get_disk_usage
net_io_counters = _psutil_osx.get_net_io_counters
disk_io_counters = _psutil_osx.get_disk_io_counters
def net_connections(kind='inet'):
# Note: on OSX this will fail with AccessDenied unless
# the process is owned by root.
ret = []
for pid in pids():
try:
cons = Process(pid).connections(kind)
except NoSuchProcess:
continue
else:
if cons:
for c in cons:
c = list(c) + [pid]
ret.append(_common.sconn(*c))
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
# --- decorator
def wrap_exceptions(fun):
"""Decorator which translates bare OSError exceptions into
@ -146,70 +181,62 @@ def wrap_exceptions(fun):
try:
return fun(self, *args, **kwargs)
except OSError:
# support for private module import
if NoSuchProcess is None or AccessDenied is None:
raise
err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
raise NoSuchProcess(self.pid, self._process_name)
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
raise
return wrapper
_status_map = {
_psutil_osx.SIDL : STATUS_IDLE,
_psutil_osx.SRUN : STATUS_RUNNING,
_psutil_osx.SSLEEP : STATUS_SLEEPING,
_psutil_osx.SSTOP : STATUS_STOPPED,
_psutil_osx.SZOMB : STATUS_ZOMBIE,
}
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_process_name"]
__slots__ = ["pid", "_name"]
def __init__(self, pid):
self.pid = pid
self._process_name = None
self._name = None
@wrap_exceptions
def get_process_name(self):
"""Return process name as a string of limited len (15)."""
return _psutil_osx.get_process_name(self.pid)
def name(self):
return cext.proc_name(self.pid)
@wrap_exceptions
def get_process_exe(self):
return _psutil_osx.get_process_exe(self.pid)
def exe(self):
return cext.proc_exe(self.pid)
@wrap_exceptions
def get_process_cmdline(self):
"""Return process cmdline as a list of arguments."""
def cmdline(self):
if not pid_exists(self.pid):
raise NoSuchProcess(self.pid, self._process_name)
return _psutil_osx.get_process_cmdline(self.pid)
raise NoSuchProcess(self.pid, self._name)
return cext.proc_cmdline(self.pid)
@wrap_exceptions
def get_process_ppid(self):
"""Return process parent pid."""
return _psutil_osx.get_process_ppid(self.pid)
def ppid(self):
return cext.proc_ppid(self.pid)
@wrap_exceptions
def get_process_cwd(self):
return _psutil_osx.get_process_cwd(self.pid)
def cwd(self):
return cext.proc_cwd(self.pid)
@wrap_exceptions
def get_process_uids(self):
real, effective, saved = _psutil_osx.get_process_uids(self.pid)
return nt_uids(real, effective, saved)
def uids(self):
real, effective, saved = cext.proc_uids(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def get_process_gids(self):
real, effective, saved = _psutil_osx.get_process_gids(self.pid)
return nt_gids(real, effective, saved)
def gids(self):
real, effective, saved = cext.proc_gids(self.pid)
return _common.pgids(real, effective, saved)
@wrap_exceptions
def get_process_terminal(self):
tty_nr = _psutil_osx.get_process_tty_nr(self.pid)
def terminal(self):
tty_nr = cext.proc_tty_nr(self.pid)
tmap = _psposix._get_terminal_map()
try:
return tmap[tty_nr]
@ -217,115 +244,98 @@ class Process(object):
return None
@wrap_exceptions
def get_memory_info(self):
"""Return a tuple with the process' RSS and VMS size."""
rss, vms = _psutil_osx.get_process_memory_info(self.pid)[:2]
return nt_meminfo(rss, vms)
_nt_ext_mem = namedtuple('meminfo', 'rss vms pfaults pageins')
def memory_info(self):
rss, vms = cext.proc_memory_info(self.pid)[:2]
return _common.pmem(rss, vms)
@wrap_exceptions
def get_ext_memory_info(self):
"""Return a tuple with the process' RSS and VMS size."""
rss, vms, pfaults, pageins = _psutil_osx.get_process_memory_info(self.pid)
return self._nt_ext_mem(rss, vms,
pfaults * _PAGESIZE,
pageins * _PAGESIZE)
def memory_info_ex(self):
rss, vms, pfaults, pageins = cext.proc_memory_info(self.pid)
return pextmem(rss, vms, pfaults * PAGESIZE, pageins * PAGESIZE)
@wrap_exceptions
def get_cpu_times(self):
user, system = _psutil_osx.get_process_cpu_times(self.pid)
return nt_cputimes(user, system)
def cpu_times(self):
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def get_process_create_time(self):
"""Return the start time of the process as a number of seconds since
the epoch."""
return _psutil_osx.get_process_create_time(self.pid)
def create_time(self):
return cext.proc_create_time(self.pid)
@wrap_exceptions
def get_num_ctx_switches(self):
return nt_ctxsw(*_psutil_osx.get_process_num_ctx_switches(self.pid))
def num_ctx_switches(self):
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def get_process_num_threads(self):
"""Return the number of threads belonging to the process."""
return _psutil_osx.get_process_num_threads(self.pid)
def num_threads(self):
return cext.proc_num_threads(self.pid)
@wrap_exceptions
def get_open_files(self):
"""Return files opened by process."""
def open_files(self):
if self.pid == 0:
return []
files = []
rawlist = _psutil_osx.get_process_open_files(self.pid)
rawlist = cext.proc_open_files(self.pid)
for path, fd in rawlist:
if isfile_strict(path):
ntuple = nt_openfile(path, fd)
ntuple = _common.popenfile(path, fd)
files.append(ntuple)
return files
@wrap_exceptions
def get_connections(self, kind='inet'):
"""Return etwork connections opened by a process as a list of
namedtuples.
"""
def connections(self, kind='inet'):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = _psutil_osx.get_process_connections(self.pid, families, types)
rawlist = cext.proc_connections(self.pid, families, types)
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
status = _TCP_STATES_TABLE[status]
nt = nt_connection(fd, fam, type, laddr, raddr, status)
status = TCP_STATUSES[status]
nt = _common.pconn(fd, fam, type, laddr, raddr, status)
ret.append(nt)
return ret
@wrap_exceptions
def get_num_fds(self):
def num_fds(self):
if self.pid == 0:
return 0
return _psutil_osx.get_process_num_fds(self.pid)
return cext.proc_num_fds(self.pid)
@wrap_exceptions
def process_wait(self, timeout=None):
def wait(self, timeout=None):
try:
return _psposix.wait_pid(self.pid, timeout)
except TimeoutExpired:
raise TimeoutExpired(self.pid, self._process_name)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)
@wrap_exceptions
def get_process_nice(self):
def nice_get(self):
return _psutil_posix.getpriority(self.pid)
@wrap_exceptions
def set_process_nice(self, value):
def nice_set(self, value):
return _psutil_posix.setpriority(self.pid, value)
@wrap_exceptions
def get_process_status(self):
code = _psutil_osx.get_process_status(self.pid)
if code in _status_map:
return _status_map[code]
return constant(-1, "?")
def status(self):
code = cext.proc_status(self.pid)
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
@wrap_exceptions
def get_process_threads(self):
"""Return the number of threads belonging to the process."""
rawlist = _psutil_osx.get_process_threads(self.pid)
def threads(self):
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = nt_thread(thread_id, utime, stime)
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
return retlist
nt_mmap_grouped = namedtuple('mmap',
'path rss private swapped dirtied ref_count shadow_depth')
nt_mmap_ext = namedtuple('mmap',
'addr perms path rss private swapped dirtied ref_count shadow_depth')
@wrap_exceptions
def get_memory_maps(self):
return _psutil_osx.get_process_memory_maps(self.pid)
def memory_maps(self):
return cext.proc_memory_maps(self.pid)

View File

@ -6,29 +6,49 @@
"""Routines common to all posix systems."""
import os
import errno
import psutil
import glob
import os
import sys
import time
import glob
from psutil._error import TimeoutExpired
from psutil._common import nt_diskinfo, usage_percent, memoize
from psutil._common import sdiskusage, usage_percent, memoize
from psutil._compat import PY3, unicode
class TimeoutExpired(Exception):
pass
def pid_exists(pid):
"""Check whether pid exists in the current process table."""
if pid < 0:
return False
if pid == 0:
# According to "man 2 kill" PID 0 has a special meaning:
# it refers to <<every process in the process group of the
# calling process>> so we don't want to go any further.
# If we get here it means this UNIX platform *does* have
# a process with id 0.
return True
try:
os.kill(pid, 0)
except OSError:
e = sys.exc_info()[1]
return e.errno == errno.EPERM
err = sys.exc_info()[1]
if err.errno == errno.ESRCH:
# ESRCH == No such process
return False
elif err.errno == errno.EPERM:
# EPERM clearly means there's a process to deny access to
return True
else:
# According to "man 2 kill" possible error values are
# (EINVAL, EPERM, ESRCH) therefore we should never get
# here. If we do let's be explicit in considering this
# an error.
raise err
else:
return True
def wait_pid(pid, timeout=None):
"""Wait for process with pid 'pid' to terminate and return its
exit status code as an integer.
@ -43,7 +63,7 @@ def wait_pid(pid, timeout=None):
def check_timeout(delay):
if timeout is not None:
if timer() >= stop_at:
raise TimeoutExpired(pid)
raise TimeoutExpired()
time.sleep(delay)
return min(delay * 2, 0.04)
@ -94,9 +114,24 @@ def wait_pid(pid, timeout=None):
# should never happen
raise RuntimeError("unknown process exit status")
def get_disk_usage(path):
def disk_usage(path):
"""Return disk usage associated with path."""
st = os.statvfs(path)
try:
st = os.statvfs(path)
except UnicodeEncodeError:
if not PY3 and isinstance(path, unicode):
# this is a bug with os.statvfs() and unicode on
# Python 2, see:
# - https://github.com/giampaolo/psutil/issues/416
# - http://bugs.python.org/issue18695
try:
path = path.encode(sys.getfilesystemencoding())
except UnicodeEncodeError:
pass
st = os.statvfs(path)
else:
raise
free = (st.f_bavail * st.f_frsize)
total = (st.f_blocks * st.f_frsize)
used = (st.f_blocks - st.f_bfree) * st.f_frsize
@ -104,7 +139,8 @@ def get_disk_usage(path):
# NB: the percentage is -5% than what shown by df due to
# reserved blocks that we are currently not considering:
# http://goo.gl/sWGbH
return nt_diskinfo(total, used, free, percent)
return sdiskusage(total, used, free, percent)
@memoize
def _get_terminal_map():

View File

@ -8,39 +8,70 @@
import errno
import os
import struct
import subprocess
import socket
import subprocess
import sys
import _psutil_sunos
import _psutil_posix
from psutil import _common
from psutil import _psposix
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
from psutil._common import usage_percent, isfile_strict
from psutil._compat import namedtuple, PY3
from psutil._common import *
import _psutil_posix
import _psutil_sunos as cext
__extra__all__ = ["CONN_IDLE", "CONN_BOUND"]
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
NUM_CPUS = os.sysconf("SC_NPROCESSORS_ONLN")
BOOT_TIME = _psutil_sunos.get_process_basic_info(0)[3]
TOTAL_PHYMEM = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE
CONN_IDLE = constant(11, "IDLE")
CONN_BOUND = constant(12, "BOUND")
CONN_IDLE = "IDLE"
CONN_BOUND = "BOUND"
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
_cputimes_ntuple = namedtuple('cputimes', 'user system idle iowait')
PROC_STATUSES = {
cext.SSLEEP: _common.STATUS_SLEEPING,
cext.SRUN: _common.STATUS_RUNNING,
cext.SZOMB: _common.STATUS_ZOMBIE,
cext.SSTOP: _common.STATUS_STOPPED,
cext.SIDL: _common.STATUS_IDLE,
cext.SONPROC: _common.STATUS_RUNNING, # same as run
cext.SWAIT: _common.STATUS_WAITING,
}
disk_io_counters = _psutil_sunos.get_disk_io_counters
net_io_counters = _psutil_sunos.get_net_io_counters
get_disk_usage = _psposix.get_disk_usage
get_system_boot_time = lambda: _psutil_sunos.get_process_basic_info(0)[3]
TCP_STATUSES = {
cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED,
cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT,
cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV,
cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1,
cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2,
cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT,
cext.TCPS_CLOSED: _common.CONN_CLOSE,
cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK,
cext.TCPS_LISTEN: _common.CONN_LISTEN,
cext.TCPS_CLOSING: _common.CONN_CLOSING,
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
cext.TCPS_IDLE: CONN_IDLE, # sunos specific
cext.TCPS_BOUND: CONN_BOUND, # sunos specific
}
scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
pextmem = namedtuple('pextmem', ['rss', 'vms'])
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked'])
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# set later from __init__.py
NoSuchProcess = None
AccessDenied = None
TimeoutExpired = None
# --- functions
disk_io_counters = cext.disk_io_counters
net_io_counters = cext.net_io_counters
disk_usage = _psposix.disk_usage
nt_virtmem_info = namedtuple('vmem', ' '.join([
# all platforms
'total', 'available', 'percent', 'used', 'free']))
def virtual_memory():
# we could have done this with kstat, but imho this is good enough
@ -49,14 +80,15 @@ def virtual_memory():
free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE
used = total - free
percent = usage_percent(used, total, _round=1)
return nt_virtmem_info(total, avail, percent, used, free)
return svmem(total, avail, percent, used, free)
def swap_memory():
sin, sout = _psutil_sunos.get_swap_mem()
sin, sout = cext.swap_mem()
# XXX
# we are supposed to get total/free by doing so:
# http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/swap/swap.c
# http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/
# 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)
@ -64,7 +96,7 @@ def swap_memory():
if PY3:
stdout = stdout.decode(sys.stdout.encoding)
if p.returncode != 0:
raise RuntimeError("'swap -l -k' failed (retcode=%s)" % retcode)
raise RuntimeError("'swap -l -k' failed (retcode=%s)" % p.returncode)
lines = stdout.strip().split('\n')[1:]
if not lines:
@ -79,31 +111,55 @@ def swap_memory():
free += int(int(f) * 1024)
used = total - free
percent = usage_percent(used, total, _round=1)
return nt_swapmeminfo(total, used, free, percent,
sin * _PAGESIZE, sout * _PAGESIZE)
return _common.sswap(total, used, free, percent,
sin * PAGE_SIZE, sout * PAGE_SIZE)
def get_pid_list():
def pids():
"""Returns a list of PIDs currently running on the system."""
return [int(x) for x in os.listdir('/proc') if x.isdigit()]
def pid_exists(pid):
"""Check for the existence of a unix pid."""
return _psposix.pid_exists(pid)
def get_system_cpu_times():
def cpu_times():
"""Return system-wide CPU times as a named tuple"""
ret = _psutil_sunos.get_system_per_cpu_times()
return _cputimes_ntuple(*[sum(x) for x in zip(*ret)])
ret = cext.per_cpu_times()
return scputimes(*[sum(x) for x in zip(*ret)])
def get_system_per_cpu_times():
def per_cpu_times():
"""Return system per-CPU times as a list of named tuples"""
ret = _psutil_sunos.get_system_per_cpu_times()
return [_cputimes_ntuple(*x) for x in ret]
ret = cext.per_cpu_times()
return [scputimes(*x) for x in ret]
def get_system_users():
def cpu_count_logical():
"""Return the number of logical CPUs in the system."""
try:
return os.sysconf("SC_NPROCESSORS_ONLN")
except ValueError:
# mimic os.cpu_count() behavior
return None
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
return cext.cpu_count_phys()
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = _psutil_sunos.get_system_users()
rawlist = cext.users()
localhost = (':0.0', ':0')
for item in rawlist:
user, tty, hostname, tstamp, user_process = item
@ -114,16 +170,17 @@ def get_system_users():
continue
if hostname in localhost:
hostname = 'localhost'
nt = nt_user(user, tty, hostname, tstamp)
nt = _common.suser(user, tty, hostname, tstamp)
retlist.append(nt)
return retlist
def disk_partitions(all=False):
"""Return system disk partitions."""
# TODO - the filtering logic should be better checked so that
# it tries to reflect 'df' as much as possible
retlist = []
partitions = _psutil_sunos.get_disk_partitions()
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
if device == 'none':
@ -132,96 +189,101 @@ def disk_partitions(all=False):
# Differently from, say, Linux, we don't have a list of
# common fs types so the best we can do, AFAIK, is to
# filter by filesystem having a total size > 0.
if not get_disk_usage(mountpoint).total:
if not disk_usage(mountpoint).total:
continue
ntuple = nt_partition(device, mountpoint, fstype, opts)
ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
retlist.append(ntuple)
return retlist
def wrap_exceptions(callable):
def net_connections(kind, _pid=-1):
"""Return socket connections. If pid == -1 return system-wide
connections (as opposed to connections opened by one process only).
Only INET sockets are returned (UNIX are not).
"""
cmap = _common.conn_tmap.copy()
if _pid == -1:
cmap.pop('unix', 0)
if kind not in cmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in cmap])))
families, types = _common.conn_tmap[kind]
rawlist = cext.net_connections(_pid, families, types)
ret = []
for item in rawlist:
fd, fam, type_, laddr, raddr, status, pid = item
if fam not in families:
continue
if type_ not in types:
continue
status = TCP_STATUSES[status]
if _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)
return ret
def wrap_exceptions(fun):
"""Call callable into a try/except clause and translate ENOENT,
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
"""
def wrapper(self, *args, **kwargs):
try:
return callable(self, *args, **kwargs)
return fun(self, *args, **kwargs)
except EnvironmentError:
# support for private module import
if NoSuchProcess is None or AccessDenied 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._process_name)
raise NoSuchProcess(self.pid, self._name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
raise
return wrapper
_status_map = {
_psutil_sunos.SSLEEP : STATUS_SLEEPING,
_psutil_sunos.SRUN : STATUS_RUNNING,
_psutil_sunos.SZOMB : STATUS_ZOMBIE,
_psutil_sunos.SSTOP : STATUS_STOPPED,
_psutil_sunos.SIDL : STATUS_IDLE,
_psutil_sunos.SONPROC : STATUS_RUNNING, # same as run
_psutil_sunos.SWAIT : STATUS_WAITING,
}
_conn_status_map = {_psutil_sunos.TCPS_ESTABLISHED : CONN_ESTABLISHED,
_psutil_sunos.TCPS_SYN_SENT : CONN_SYN_SENT,
_psutil_sunos.TCPS_SYN_RCVD : CONN_SYN_RECV,
_psutil_sunos.TCPS_FIN_WAIT_1 : CONN_FIN_WAIT1,
_psutil_sunos.TCPS_FIN_WAIT_2 : CONN_FIN_WAIT2,
_psutil_sunos.TCPS_TIME_WAIT : CONN_TIME_WAIT,
_psutil_sunos.TCPS_CLOSED : CONN_CLOSE,
_psutil_sunos.TCPS_CLOSE_WAIT : CONN_CLOSE_WAIT,
_psutil_sunos.TCPS_LAST_ACK : CONN_LAST_ACK,
_psutil_sunos.TCPS_LISTEN : CONN_LISTEN,
_psutil_sunos.TCPS_CLOSING : CONN_CLOSING,
_psutil_sunos.PSUTIL_CONN_NONE : CONN_NONE,
_psutil_sunos.TCPS_IDLE : CONN_IDLE, # sunos specific
_psutil_sunos.TCPS_BOUND : CONN_BOUND, # sunos specific
}
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_process_name"]
__slots__ = ["pid", "_name"]
def __init__(self, pid):
self.pid = pid
self._process_name = None
self._name = None
@wrap_exceptions
def get_process_name(self):
def name(self):
# note: max len == 15
return _psutil_sunos.get_process_name_and_args(self.pid)[0]
return cext.proc_name_and_args(self.pid)[0]
@wrap_exceptions
def get_process_exe(self):
def exe(self):
# Will be guess later from cmdline but we want to explicitly
# invoke cmdline here in order to get an AccessDenied
# exception if the user has not enough privileges.
self.get_process_cmdline()
self.cmdline()
return ""
@wrap_exceptions
def get_process_cmdline(self):
return _psutil_sunos.get_process_name_and_args(self.pid)[1].split(' ')
def cmdline(self):
return cext.proc_name_and_args(self.pid)[1].split(' ')
@wrap_exceptions
def get_process_create_time(self):
return _psutil_sunos.get_process_basic_info(self.pid)[3]
def create_time(self):
return cext.proc_basic_info(self.pid)[3]
@wrap_exceptions
def get_process_num_threads(self):
return _psutil_sunos.get_process_basic_info(self.pid)[5]
def num_threads(self):
return cext.proc_basic_info(self.pid)[5]
@wrap_exceptions
def get_process_nice(self):
def nice_get(self):
# For some reason getpriority(3) return ESRCH (no such process)
# for certain low-pid processes, no matter what (even as root).
# The process actually exists though, as it has a name,
@ -235,43 +297,44 @@ class Process(object):
err = sys.exc_info()[1]
if err.errno in (errno.ENOENT, errno.ESRCH):
if pid_exists(self.pid):
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
raise
@wrap_exceptions
def set_process_nice(self, value):
def nice_set(self, value):
if self.pid in (2, 3):
# Special case PIDs: internally setpriority(3) return ESRCH
# (no such process), no matter what.
# The process actually exists though, as it has a name,
# creation time, etc.
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
return _psutil_posix.setpriority(self.pid, value)
@wrap_exceptions
def get_process_ppid(self):
return _psutil_sunos.get_process_basic_info(self.pid)[0]
def ppid(self):
return cext.proc_basic_info(self.pid)[0]
@wrap_exceptions
def get_process_uids(self):
real, effective, saved, _, _, _ = _psutil_sunos.get_process_cred(self.pid)
return nt_uids(real, effective, saved)
def uids(self):
real, effective, saved, _, _, _ = cext.proc_cred(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def get_process_gids(self):
_, _, _, real, effective, saved = _psutil_sunos.get_process_cred(self.pid)
return nt_uids(real, effective, saved)
def gids(self):
_, _, _, real, effective, saved = cext.proc_cred(self.pid)
return _common.puids(real, effective, saved)
@wrap_exceptions
def get_cpu_times(self):
user, system = _psutil_sunos.get_process_cpu_times(self.pid)
return nt_cputimes(user, system)
def cpu_times(self):
user, system = cext.proc_cpu_times(self.pid)
return _common.pcputimes(user, system)
@wrap_exceptions
def get_process_terminal(self):
def terminal(self):
hit_enoent = False
tty = wrap_exceptions(_psutil_sunos.get_process_basic_info(self.pid)[0])
if tty != _psutil_sunos.PRNODEV:
tty = wrap_exceptions(
cext.proc_basic_info(self.pid)[0])
if tty != cext.PRNODEV:
for x in (0, 1, 2, 255):
try:
return os.readlink('/proc/%d/path/%d' % (self.pid, x))
@ -286,7 +349,7 @@ class Process(object):
os.stat('/proc/%s' % self.pid)
@wrap_exceptions
def get_process_cwd(self):
def cwd(self):
# /proc/PID/path/cwd may not be resolved by readlink() even if
# it exists (ls shows it). If that's the case and the process
# is still alive return None (we can return None also on BSD).
@ -301,30 +364,30 @@ class Process(object):
raise
@wrap_exceptions
def get_memory_info(self):
ret = _psutil_sunos.get_process_basic_info(self.pid)
def memory_info(self):
ret = cext.proc_basic_info(self.pid)
rss, vms = ret[1] * 1024, ret[2] * 1024
return nt_meminfo(rss, vms)
return _common.pmem(rss, vms)
# it seems Solaris uses rss and vms only
get_ext_memory_info = get_memory_info
memory_info_ex = memory_info
@wrap_exceptions
def get_process_status(self):
code = _psutil_sunos.get_process_basic_info(self.pid)[6]
if code in _status_map:
return _status_map[code]
return constant(-1, "?")
def status(self):
code = cext.proc_basic_info(self.pid)[6]
# XXX is '?' legit? (we're not supposed to return it anyway)
return PROC_STATUSES.get(code, '?')
@wrap_exceptions
def get_process_threads(self):
def threads(self):
ret = []
tids = os.listdir('/proc/%d/lwp' % self.pid)
hit_enoent = False
for tid in tids:
tid = int(tid)
try:
utime, stime = _psutil_sunos.query_process_thread(self.pid, tid)
utime, stime = cext.query_process_thread(
self.pid, tid)
except EnvironmentError:
# ENOENT == thread gone in meantime
err = sys.exc_info()[1]
@ -333,7 +396,7 @@ class Process(object):
continue
raise
else:
nt = nt_thread(tid, utime, stime)
nt = _common.pthread(tid, utime, stime)
ret.append(nt)
if hit_enoent:
# raise NSP if the process disappeared on us
@ -341,7 +404,7 @@ class Process(object):
return ret
@wrap_exceptions
def get_open_files(self):
def open_files(self):
retlist = []
hit_enoent = False
pathdir = '/proc/%d/path' % self.pid
@ -359,7 +422,7 @@ class Process(object):
raise
else:
if isfile_strict(file):
retlist.append(nt_openfile(file, int(fd)))
retlist.append(_common.popenfile(file, int(fd)))
if hit_enoent:
# raise NSP if the process disappeared on us
os.stat('/proc/%s' % self.pid)
@ -371,16 +434,16 @@ class Process(object):
# does not include this part! Argh!!)
cmd = "pfiles %s" % pid
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if PY3:
stdout, stderr = [x.decode(sys.stdout.encoding)
for x in (stdout, stderr)]
if p.returncode != 0:
if 'permission denied' in stderr.lower():
raise AccessDenied(self.pid, self._process_name)
raise AccessDenied(self.pid, self._name)
if 'no such process' in stderr.lower():
raise NoSuchProcess(self.pid, self._process_name)
raise NoSuchProcess(self.pid, self._name)
raise RuntimeError("%r command error\n%s" % (cmd, stderr))
lines = stdout.split('\n')[2:]
@ -388,44 +451,29 @@ class Process(object):
line = line.lstrip()
if line.startswith('sockname: AF_UNIX'):
path = line.split(' ', 2)[2]
type = lines[i-2].strip()
type = lines[i - 2].strip()
if type == 'SOCK_STREAM':
type = socket.SOCK_STREAM
elif type == 'SOCK_DGRAM':
type = socket.SOCK_DGRAM
else:
type = -1
yield (-1, socket.AF_UNIX, type, path, "", CONN_NONE)
yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE)
@wrap_exceptions
def get_connections(self, kind='inet'):
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = _psutil_sunos.get_process_connections(self.pid, families, types)
def connections(self, kind='inet'):
ret = net_connections(kind, _pid=self.pid)
# The underlying C implementation retrieves all OS connections
# and filters them by PID. At this point we can't tell whether
# an empty list means there were no connections for process or
# process is no longer active so we force NSP in case the PID
# is no longer there.
if not rawlist:
if not ret:
os.stat('/proc/%s' % self.pid) # will raise NSP if process is gone
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status = item
if fam not in families:
continue
if type not in types:
continue
status = _conn_status_map[status]
nt = nt_connection(fd, fam, type, laddr, raddr, status)
ret.append(nt)
# UNIX sockets
if socket.AF_UNIX in families:
ret.extend([nt_connection(*conn) for conn in \
if kind in ('all', 'unix'):
ret.extend([_common.pconn(*conn) for conn in
self._get_unix_sockets(self.pid)])
return ret
@ -433,12 +481,13 @@ class Process(object):
nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked')
@wrap_exceptions
def get_memory_maps(self):
def memory_maps(self):
def toaddr(start, end):
return '%s-%s' % (hex(start)[2:].strip('L'), hex(end)[2:].strip('L'))
return '%s-%s' % (hex(start)[2:].strip('L'),
hex(end)[2:].strip('L'))
retlist = []
rawlist = _psutil_sunos.get_process_memory_maps(self.pid)
rawlist = cext.proc_memory_maps(self.pid)
hit_enoent = False
for item in rawlist:
addr, addrsize, perm, name, rss, anon, locked = item
@ -466,16 +515,19 @@ class Process(object):
return retlist
@wrap_exceptions
def get_num_fds(self):
return len(os.listdir("/proc/%s/fd" % self.pid))
def num_fds(self):
return len(os.listdir("/proc/%s/fd" % self.pid))
@wrap_exceptions
def get_num_ctx_switches(self):
return nt_ctxsw(*_psutil_sunos.get_process_num_ctx_switches(self.pid))
def num_ctx_switches(self):
return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid))
@wrap_exceptions
def process_wait(self, timeout=None):
def wait(self, timeout=None):
try:
return _psposix.wait_pid(self.pid, timeout)
except TimeoutExpired:
raise TimeoutExpired(self.pid, self._process_name)
except _psposix.TimeoutExpired:
# support for private module import
if TimeoutExpired is None:
raise
raise TimeoutExpired(timeout, self.pid, self._name)

File diff suppressed because it is too large Load Diff

View File

@ -2,49 +2,50 @@
* 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.
*
* BSD platform-specific module methods for _psutil_bsd
*/
#include <Python.h>
// --- per-process functions
static PyObject* get_process_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_process_name(PyObject* self, PyObject* args);
static PyObject* get_process_exe(PyObject* self, PyObject* args);
static PyObject* get_process_cmdline(PyObject* self, PyObject* args);
static PyObject* get_process_ppid(PyObject* self, PyObject* args);
static PyObject* get_process_uids(PyObject* self, PyObject* args);
static PyObject* get_process_gids(PyObject* self, PyObject* args);
static PyObject* get_process_connections(PyObject* self, PyObject* args);
static PyObject* get_process_create_time(PyObject* self, PyObject* args);
static PyObject* get_process_memory_info(PyObject* self, PyObject* args);
static PyObject* get_process_num_threads(PyObject* self, PyObject* args);
static PyObject* get_process_num_fds(PyObject* self, PyObject* args);
static PyObject* get_process_threads(PyObject* self, PyObject* args);
static PyObject* get_process_status(PyObject* self, PyObject* args);
static PyObject* get_process_io_counters(PyObject* self, PyObject* args);
static PyObject* get_process_tty_nr(PyObject* self, PyObject* args);
static PyObject* get_process_memory_maps(PyObject* self, PyObject* args);
static PyObject* get_process_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
static PyObject* psutil_proc_connections(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args);
static PyObject* psutil_proc_exe(PyObject* self, PyObject* args);
static PyObject* psutil_proc_gids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_ppid(PyObject* self, PyObject* args);
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);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
static PyObject* get_process_open_files(PyObject* self, PyObject* args);
static PyObject* get_process_cwd(PyObject* self, PyObject* args);
static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args);
#endif
// --- system-related functions
static PyObject* get_pid_list(PyObject* self, PyObject* args);
static PyObject* get_num_cpus(PyObject* self, PyObject* args);
static PyObject* get_virtual_mem(PyObject* self, PyObject* args);
static PyObject* get_swap_mem(PyObject* self, PyObject* args);
static PyObject* get_system_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_pids(PyObject* self, PyObject* args);
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000
static PyObject* get_system_per_cpu_times(PyObject* self, PyObject* args);
#endif
static PyObject* get_system_boot_time(PyObject* self, PyObject* args);
static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
static PyObject* get_net_io_counters(PyObject* self, PyObject* args);
static PyObject* get_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* get_system_users(PyObject* self, PyObject* args);
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
#endif

View File

@ -22,6 +22,7 @@ NoSuchProcess(void) {
return NULL;
}
/*
* Set OSError(errno=EACCES, strerror="Permission denied") Python exception.
*/

View File

@ -6,6 +6,5 @@
#include <Python.h>
PyObject* NoSuchProcess(void);
PyObject* AccessDenied(void);
PyObject* NoSuchProcess(void);

View File

@ -6,23 +6,42 @@
* Linux-specific functions.
*/
#define _GNU_SOURCE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <Python.h>
#include <errno.h>
#include <stdlib.h>
#include <mntent.h>
#include <features.h>
#include <utmp.h>
#include <sched.h>
#include <linux/version.h>
#include <sys/syscall.h>
#include <sys/sysinfo.h>
#include <linux/unistd.h>
#include "_psutil_linux.h"
/* The minimum number of CPUs allocated in a cpu_set_t */
static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT;
#define HAS_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set)
// Linux >= 2.6.13
#define PSUTIL_HAVE_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set)
#if HAS_IOPRIO
// Linux >= 2.6.36 (supposedly) and glibc >= 13
#define PSUTIL_HAVE_PRLIMIT \
(LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && \
(__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 13) && \
defined(__NR_prlimit64)
#if PSUTIL_HAVE_PRLIMIT
#define _FILE_OFFSET_BITS 64
#include <time.h>
#include <sys/resource.h>
#endif
#if PSUTIL_HAVE_IOPRIO
enum {
IOPRIO_WHO_PROCESS = 1,
};
@ -39,19 +58,19 @@ ioprio_set(int which, int who, int ioprio)
return syscall(__NR_ioprio_set, which, who, ioprio);
}
#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_CLASS_SHIFT 13
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data)
/*
* Return a (ioclass, iodata) Python tuple representing process I/O priority.
*/
static PyObject*
linux_ioprio_get(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_ioprio_get(PyObject *self, PyObject *args)
{
long pid;
int ioprio, ioclass, iodata;
@ -73,8 +92,8 @@ linux_ioprio_get(PyObject* self, PyObject* args)
* ioclass can be either IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE
* or 0. iodata goes from 0 to 7 depending on ioclass specified.
*/
static PyObject*
linux_ioprio_set(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_ioprio_set(PyObject *self, PyObject *args)
{
long pid;
int ioprio, ioclass, iodata;
@ -94,17 +113,80 @@ linux_ioprio_set(PyObject* self, PyObject* args)
#endif
#if PSUTIL_HAVE_PRLIMIT
/*
* A wrapper around prlimit(2); sets process resource limits.
* This can be used for both get and set, in which case extra
* 'soft' and 'hard' args must be provided.
*/
static PyObject *
psutil_linux_prlimit(PyObject *self, PyObject *args)
{
long pid;
int ret, resource;
struct rlimit old, new;
struct rlimit *newp = NULL;
PyObject *soft = NULL;
PyObject *hard = NULL;
if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard)) {
return NULL;
}
// get
if (soft == NULL && hard == NULL) {
ret = prlimit(pid, resource, NULL, &old);
if (ret == -1)
return PyErr_SetFromErrno(PyExc_OSError);
#if defined(PSUTIL_HAVE_LONG_LONG)
if (sizeof(old.rlim_cur) > sizeof(long)) {
return Py_BuildValue("LL",
(PY_LONG_LONG)old.rlim_cur,
(PY_LONG_LONG)old.rlim_max);
}
#endif
return Py_BuildValue("ll", (long)old.rlim_cur, (long)old.rlim_max);
}
// set
else {
#if defined(PSUTIL_HAVE_LARGEFILE_SUPPORT)
new.rlim_cur = PyLong_AsLongLong(soft);
if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
new.rlim_max = PyLong_AsLongLong(hard);
if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
#else
new.rlim_cur = PyLong_AsLong(soft);
if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
new.rlim_max = PyLong_AsLong(hard);
if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
return NULL;
#endif
newp = &new;
ret = prlimit(pid, resource, newp, &old);
if (ret == -1)
return PyErr_SetFromErrno(PyExc_OSError);
Py_INCREF(Py_None);
return Py_None;
}
}
#endif
/*
* Return disk mounted partitions as a list of tuples including device,
* mount point and filesystem type
*/
static PyObject*
get_disk_partitions(PyObject* self, PyObject* args)
static PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args)
{
FILE *file = NULL;
struct mntent *entry;
PyObject* py_retlist = PyList_New(0);
PyObject* py_tuple = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL)
return NULL;
@ -114,7 +196,7 @@ get_disk_partitions(PyObject* self, PyObject* args)
file = setmntent(MOUNTED, "r");
Py_END_ALLOW_THREADS
if ((file == 0) || (file == NULL)) {
PyErr_SetFromErrno(PyExc_OSError);
PyErr_SetFromErrnoWithFilename(PyExc_OSError, MOUNTED);
goto error;
}
@ -123,10 +205,11 @@ get_disk_partitions(PyObject* self, PyObject* args)
PyErr_Format(PyExc_RuntimeError, "getmntent() failed");
goto error;
}
py_tuple = Py_BuildValue("(ssss)", entry->mnt_fsname, // device
entry->mnt_dir, // mount point
entry->mnt_type, // fs type
entry->mnt_opts); // options
py_tuple = Py_BuildValue("(ssss)",
entry->mnt_fsname, // device
entry->mnt_dir, // mount point
entry->mnt_type, // fs type
entry->mnt_opts); // options
if (! py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
@ -148,16 +231,17 @@ error:
/*
* A wrapper around sysinfo(), return system memory usage statistics.
*/
static PyObject*
get_sysinfo(PyObject* self, PyObject* args)
static PyObject *
psutil_linux_sysinfo(PyObject *self, PyObject *args)
{
struct sysinfo info;
if (sysinfo(&info) != 0) {
return PyErr_SetFromErrno(PyExc_OSError);
}
// note: BOOT_TIME might also be determined from here
return Py_BuildValue("(KKKKKK)",
// note: boot time might also be determined from here
return Py_BuildValue(
"(KKKKKK)",
(unsigned long long)info.totalram * info.mem_unit, // total
(unsigned long long)info.freeram * info.mem_unit, // free
(unsigned long long)info.bufferram * info.mem_unit, // buffer
@ -168,51 +252,177 @@ get_sysinfo(PyObject* self, PyObject* args)
/*
* Return process CPU affinity as a Python long (the bitmask)
* Return process CPU affinity as a Python list
* The dual implementation exists because of:
* https://github.com/giampaolo/psutil/issues/536
*/
static PyObject*
get_process_cpu_affinity(PyObject* self, PyObject* args)
#ifdef CPU_ALLOC
static PyObject *
psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args)
{
unsigned long mask;
unsigned int len = sizeof(mask);
int cpu, ncpus, count, cpucount_s;
long pid;
size_t setsize;
cpu_set_t *mask = NULL;
PyObject *res = NULL;
if (!PyArg_ParseTuple(args, "i", &pid)) {
return NULL;
}
if (sched_getaffinity(pid, len, (cpu_set_t *)&mask) < 0) {
ncpus = NCPUS_START;
while (1) {
setsize = CPU_ALLOC_SIZE(ncpus);
mask = CPU_ALLOC(ncpus);
if (mask == NULL)
return PyErr_NoMemory();
if (sched_getaffinity(pid, setsize, mask) == 0)
break;
CPU_FREE(mask);
if (errno != EINVAL)
return PyErr_SetFromErrno(PyExc_OSError);
if (ncpus > INT_MAX / 2) {
PyErr_SetString(PyExc_OverflowError, "could not allocate "
"a large enough CPU set");
return NULL;
}
ncpus = ncpus * 2;
}
res = PyList_New(0);
if (res == NULL)
goto error;
cpucount_s = CPU_COUNT_S(setsize, mask);
for (cpu = 0, count = cpucount_s; count; cpu++) {
if (CPU_ISSET_S(cpu, setsize, mask)) {
#if PY_MAJOR_VERSION >= 3
PyObject *cpu_num = PyLong_FromLong(cpu);
#else
PyObject *cpu_num = PyInt_FromLong(cpu);
#endif
--count;
if (cpu_num == NULL)
goto error;
if (PyList_Append(res, cpu_num)) {
Py_DECREF(cpu_num);
goto error;
}
Py_DECREF(cpu_num);
}
}
CPU_FREE(mask);
return res;
error:
if (mask)
CPU_FREE(mask);
Py_XDECREF(res);
return NULL;
}
#else
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;
if (!PyArg_ParseTuple(args, "i", &pid)) {
return NULL;
}
CPU_ZERO(&cpuset);
if (sched_getaffinity(pid, len, &cpuset) < 0) {
return PyErr_SetFromErrno(PyExc_OSError);
}
return Py_BuildValue("l", mask);
}
ret_list = PyList_New(0);
for (i = 0; i < CPU_SETSIZE; ++i) {
if (CPU_ISSET(i, &cpuset)) {
PyList_Append(ret_list, Py_BuildValue("i", i));
}
}
return ret_list;
}
#endif
/*
* Set process CPU affinity; expects a bitmask
*/
static PyObject*
set_process_cpu_affinity(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args)
{
unsigned long mask;
unsigned int len = sizeof(mask);
cpu_set_t cpu_set;
size_t len;
long pid;
int i, seq_len;
PyObject *py_cpu_set;
PyObject *py_cpu_seq = NULL;
if (!PyArg_ParseTuple(args, "ll", &pid, &mask)) {
return NULL;
if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) {
goto error;
}
if (sched_setaffinity(pid, len, (cpu_set_t *)&mask)) {
return PyErr_SetFromErrno(PyExc_OSError);
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");
goto error;
}
py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer");
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++) {
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);
}
len = sizeof(cpu_set);
if (sched_setaffinity(pid, len, &cpu_set)) {
PyErr_SetFromErrno(PyExc_OSError);
goto error;
}
Py_DECREF(py_cpu_seq);
Py_INCREF(Py_None);
return Py_None;
error:
if (py_cpu_seq != NULL) {
Py_DECREF(py_cpu_seq);
}
return NULL;
}
/*
* Return currently connected users as a list of tuples.
*/
static PyObject*
get_system_users(PyObject* self, PyObject* args)
static PyObject *
psutil_users(PyObject *self, PyObject *args)
{
PyObject *ret_list = PyList_New(0);
PyObject *tuple = NULL;
@ -221,7 +431,6 @@ get_system_users(PyObject* self, PyObject* args)
if (ret_list == NULL)
return NULL;
setutent();
while (NULL != (ut = getutent())) {
tuple = NULL;
@ -230,14 +439,15 @@ get_system_users(PyObject* self, PyObject* args)
user_proc = Py_True;
else
user_proc = Py_False;
tuple = Py_BuildValue("(sssfO)",
tuple = Py_BuildValue(
"(sssfO)",
ut->ut_user, // username
ut->ut_line, // tty
ut->ut_host, // hostname
(float)ut->ut_tv.tv_sec, // tstamp
user_proc // (bool) user process
);
if (! tuple)
if (! tuple)
goto error;
if (PyList_Append(ret_list, tuple))
goto error;
@ -261,25 +471,38 @@ error:
static PyMethodDef
PsutilMethods[] =
{
#if HAS_IOPRIO
{"ioprio_get", linux_ioprio_get, METH_VARARGS,
"Get process I/O priority"},
{"ioprio_set", linux_ioprio_set, METH_VARARGS,
"Set process I/O priority"},
#endif
{"get_disk_partitions", get_disk_partitions, METH_VARARGS,
"Return disk mounted partitions as a list of tuples including "
"device, mount point and filesystem type"},
{"get_sysinfo", get_sysinfo, METH_VARARGS,
"A wrapper around sysinfo(), return system memory usage statistics"},
{"get_process_cpu_affinity", get_process_cpu_affinity, METH_VARARGS,
"Return process CPU affinity as a Python long (the bitmask)."},
{"set_process_cpu_affinity", set_process_cpu_affinity, METH_VARARGS,
"Set process CPU affinity; expects a bitmask."},
{"get_system_users", get_system_users, METH_VARARGS,
"Return currently connected users as a list of tuples"},
// --- per-process functions
{NULL, NULL, 0, NULL}
#if PSUTIL_HAVE_IOPRIO
{"proc_ioprio_get", psutil_proc_ioprio_get, METH_VARARGS,
"Get process I/O priority"},
{"proc_ioprio_set", psutil_proc_ioprio_set, METH_VARARGS,
"Set process I/O priority"},
#endif
{"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS,
"Return process CPU affinity as a Python long (the bitmask)."},
{"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS,
"Set process CPU affinity; expects a bitmask."},
// --- system related functions
{"disk_partitions", psutil_disk_partitions, METH_VARARGS,
"Return disk mounted partitions as a list of tuples including "
"device, mount point and filesystem type"},
{"users", psutil_users, METH_VARARGS,
"Return currently connected users as a list of tuples"},
// --- linux specific
{"linux_sysinfo", psutil_linux_sysinfo, METH_VARARGS,
"A wrapper around sysinfo(), return system memory usage statistics"},
#if PSUTIL_HAVE_PRLIMIT
{"linux_prlimit", psutil_linux_prlimit, METH_VARARGS,
"Get or set process resource limits."},
#endif
{NULL, NULL, 0, NULL}
};
struct module_state {
@ -307,22 +530,21 @@ psutil_linux_clear(PyObject *m) {
}
static struct PyModuleDef
moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_linux",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_linux_traverse,
psutil_linux_clear,
NULL
moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_linux",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_linux_traverse,
psutil_linux_clear,
NULL
};
#define INITERROR return NULL
PyObject *
PyInit__psutil_linux(void)
PyMODINIT_FUNC PyInit__psutil_linux(void)
#else
#define INITERROR return
@ -335,6 +557,38 @@ void init_psutil_linux(void)
#else
PyObject *module = Py_InitModule("_psutil_linux", PsutilMethods);
#endif
#if PSUTIL_HAVE_PRLIMIT
PyModule_AddIntConstant(module, "RLIM_INFINITY", RLIM_INFINITY);
PyModule_AddIntConstant(module, "RLIMIT_AS", RLIMIT_AS);
PyModule_AddIntConstant(module, "RLIMIT_CORE", RLIMIT_CORE);
PyModule_AddIntConstant(module, "RLIMIT_CPU", RLIMIT_CPU);
PyModule_AddIntConstant(module, "RLIMIT_DATA", RLIMIT_DATA);
PyModule_AddIntConstant(module, "RLIMIT_FSIZE", RLIMIT_FSIZE);
PyModule_AddIntConstant(module, "RLIMIT_LOCKS", RLIMIT_LOCKS);
PyModule_AddIntConstant(module, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK);
PyModule_AddIntConstant(module, "RLIMIT_NOFILE", RLIMIT_NOFILE);
PyModule_AddIntConstant(module, "RLIMIT_NPROC", RLIMIT_NPROC);
PyModule_AddIntConstant(module, "RLIMIT_RSS", RLIMIT_RSS);
PyModule_AddIntConstant(module, "RLIMIT_STACK", RLIMIT_STACK);
#ifdef RLIMIT_MSGQUEUE
PyModule_AddIntConstant(module, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE);
#endif
#ifdef RLIMIT_NICE
PyModule_AddIntConstant(module, "RLIMIT_NICE", RLIMIT_NICE);
#endif
#ifdef RLIMIT_RTPRIO
PyModule_AddIntConstant(module, "RLIMIT_RTPRIO", RLIMIT_RTPRIO);
#endif
#ifdef RLIMIT_RTTIME
PyModule_AddIntConstant(module, "RLIMIT_RTTIME", RLIMIT_RTTIME);
#endif
#ifdef RLIMIT_SIGPENDING
PyModule_AddIntConstant(module, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING);
#endif
#endif
if (module == NULL) {
INITERROR;
}

View File

@ -2,16 +2,19 @@
* 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.
*
* LINUX specific module methods for _psutil_linux
*/
#include <Python.h>
static PyObject* linux_ioprio_get(PyObject* self, PyObject* args);
static PyObject* linux_ioprio_set(PyObject* self, PyObject* args);
static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
static PyObject* get_sysinfo(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_affinity(PyObject* self, PyObject* args);
static PyObject* set_process_cpu_affinity(PyObject* self, PyObject* args);
static PyObject* get_system_users(PyObject* self, PyObject* args);
// process
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_ioprio_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args);
// system
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);

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Windows platform-specific module methods for _psutil_mswindows
*/
#include <Python.h>
#include <windows.h>
// --- per-process functions
static PyObject* get_process_name(PyObject* self, PyObject* args);
static PyObject* get_process_cmdline(PyObject* self, PyObject* args);
static PyObject* get_process_exe(PyObject* self, PyObject* args);
static PyObject* get_process_ppid(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_process_create_time(PyObject* self, PyObject* args);
static PyObject* get_process_memory_info(PyObject* self, PyObject* args);
static PyObject* get_process_cwd(PyObject* self, PyObject* args);
static PyObject* get_process_open_files(PyObject* self, PyObject* args);
static PyObject* get_process_username(PyObject* self, PyObject* args);
static PyObject* get_process_connections(PyObject* self, PyObject* args);
static PyObject* get_process_num_threads(PyObject* self, PyObject* args);
static PyObject* get_process_threads(PyObject* self, PyObject* args);
static PyObject* get_process_priority(PyObject* self, PyObject* args);
static PyObject* set_process_priority(PyObject* self, PyObject* args);
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
static PyObject* get_process_io_priority(PyObject* self, PyObject* args);
static PyObject* set_process_io_priority(PyObject* self, PyObject* args);
#endif
static PyObject* get_process_io_counters(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_affinity(PyObject* self, PyObject* args);
static PyObject* set_process_cpu_affinity(PyObject* self, PyObject* args);
static PyObject* get_process_num_handles(PyObject* self, PyObject* args);
static PyObject* get_process_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* get_process_memory_maps(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_times_2(PyObject* self, PyObject* args);
static PyObject* get_process_create_time_2(PyObject* self, PyObject* args);
static PyObject* get_process_num_handles_2(PyObject* self, PyObject* args);
static PyObject* get_process_io_counters_2(PyObject* self, PyObject* args);
static PyObject* get_process_memory_info_2(PyObject* self, PyObject* args);
static PyObject* suspend_process(PyObject* self, PyObject* args);
static PyObject* resume_process(PyObject* self, PyObject* args);
static PyObject* is_process_suspended(PyObject* self, PyObject* args);
static PyObject* process_wait(PyObject* self, PyObject* args);
static PyObject* kill_process(PyObject* self, PyObject* args);
// --- system-related functions
static PyObject* get_pid_list(PyObject* self, PyObject* args);
static PyObject* get_num_cpus(PyObject* self, PyObject* args);
static PyObject* get_system_boot_time(PyObject* self, PyObject* args);
static PyObject* get_virtual_mem(PyObject* self, PyObject* args);
static PyObject* get_system_cpu_times(PyObject* self, PyObject* args);
static PyObject* pid_exists(PyObject* self, PyObject* args);
static PyObject* get_disk_usage(PyObject* self, PyObject* args);
static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
static PyObject* get_net_io_counters(PyObject* self, PyObject* args);
static PyObject* get_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* get_system_users(PyObject* self, PyObject* args);
// --- windows API bindings
static PyObject* win32_QueryDosDevice(PyObject* self, PyObject* args);
// --- internal
int suspend_resume_process(DWORD pid, int suspend);

File diff suppressed because it is too large Load Diff

View File

@ -2,41 +2,40 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* OS X platform-specific module methods for _psutil_osx
*/
#include <Python.h>
// --- per-process functions
static PyObject* get_process_name(PyObject* self, PyObject* args);
static PyObject* get_process_cmdline(PyObject* self, PyObject* args);
static PyObject* get_process_cwd(PyObject* self, PyObject* args);
static PyObject* get_process_exe(PyObject* self, PyObject* args);
static PyObject* get_process_ppid(PyObject* self, PyObject* args);
static PyObject* get_process_uids(PyObject* self, PyObject* args);
static PyObject* get_process_gids(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_process_create_time(PyObject* self, PyObject* args);
static PyObject* get_process_memory_info(PyObject* self, PyObject* args);
static PyObject* get_process_num_threads(PyObject* self, PyObject* args);
static PyObject* get_process_status(PyObject* self, PyObject* args);
static PyObject* get_process_threads(PyObject* self, PyObject* args);
static PyObject* get_process_open_files(PyObject* self, PyObject* args);
static PyObject* get_process_connections(PyObject* self, PyObject* args);
static PyObject* get_process_num_fds(PyObject* self, PyObject* args);
static PyObject* get_process_tty_nr(PyObject* self, PyObject* args);
static PyObject* get_process_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args);
static PyObject* psutil_proc_connections(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_create_time(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_gids(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_fds(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_ppid(PyObject* self, PyObject* args);
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);
// --- system-related functions
static PyObject* get_pid_list(PyObject* self, PyObject* args);
static PyObject* get_num_cpus(PyObject* self, PyObject* args);
static PyObject* get_virtual_mem(PyObject* self, PyObject* args);
static PyObject* get_swap_mem(PyObject* self, PyObject* args);
static PyObject* get_system_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_system_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_system_boot_time(PyObject* self, PyObject* args);
static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
static PyObject* get_net_io_counters(PyObject* self, PyObject* args);
static PyObject* get_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* get_system_users(PyObject* self, PyObject* args);
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_pids(PyObject* self, PyObject* args);
static PyObject* psutil_swap_mem(PyObject* self, PyObject* args);
static PyObject* psutil_users(PyObject* self, PyObject* args);
static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);

View File

@ -17,8 +17,8 @@
/*
* Given a PID return process priority as a Python integer.
*/
static PyObject*
posix_getpriority(PyObject* self, PyObject* args)
static PyObject *
psutil_posix_getpriority(PyObject *self, PyObject *args)
{
long pid;
int priority;
@ -33,11 +33,12 @@ posix_getpriority(PyObject* self, PyObject* args)
return Py_BuildValue("i", priority);
}
/*
* Given a PID and a value change process priority.
*/
static PyObject*
posix_setpriority(PyObject* self, PyObject* args)
static PyObject *
psutil_posix_setpriority(PyObject *self, PyObject *args)
{
long pid;
int priority;
@ -60,11 +61,11 @@ posix_setpriority(PyObject* self, PyObject* args)
static PyMethodDef
PsutilMethods[] =
{
{"getpriority", posix_getpriority, METH_VARARGS,
"Return process priority"},
{"setpriority", posix_setpriority, METH_VARARGS,
"Set process priority"},
{NULL, NULL, 0, NULL}
{"getpriority", psutil_posix_getpriority, METH_VARARGS,
"Return process priority"},
{"setpriority", psutil_posix_setpriority, METH_VARARGS,
"Set process priority"},
{NULL, NULL, 0, NULL}
};
struct module_state {
@ -91,23 +92,21 @@ psutil_posix_clear(PyObject *m) {
return 0;
}
static struct PyModuleDef
moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_posix",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_posix_traverse,
psutil_posix_clear,
NULL
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_posix",
NULL,
sizeof(struct module_state),
PsutilMethods,
NULL,
psutil_posix_traverse,
psutil_posix_clear,
NULL
};
#define INITERROR return NULL
PyObject *
PyInit__psutil_posix(void)
PyMODINIT_FUNC PyInit__psutil_posix(void)
#else
#define INITERROR return

View File

@ -2,11 +2,9 @@
* 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.
*
* POSIX specific module methods for _psutil_posix
*/
#include <Python.h>
static PyObject* posix_getpriority(PyObject* self, PyObject* args);
static PyObject* posix_setpriority(PyObject* self, PyObject* args);
static PyObject* psutil_posix_getpriority(PyObject* self, PyObject* args);
static PyObject* psutil_posix_setpriority(PyObject* self, PyObject* args);

View File

@ -9,6 +9,7 @@
* this in Cython which I later on translated in C.
*/
#include <Python.h>
// fix for "Cannot use procfs in the large file compilation environment"
@ -17,6 +18,10 @@
#undef _FILE_OFFSET_BITS
#define _STRUCTURED_PROC 1
// fix compilation issue on SunOS 5.10, see:
// https://github.com/giampaolo/psutil/issues/421
#define NEW_MIB_COMPLIANT
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/proc.h>
@ -72,8 +77,8 @@ psutil_file_to_struct(char *path, void *fstruct, size_t size)
* Return process ppid, rss, vms, ctime, nice, nthreads, status and tty
* as a Python tuple.
*/
static PyObject*
get_process_basic_info(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_basic_info(PyObject *self, PyObject *args)
{
int pid;
char path[100];
@ -93,15 +98,15 @@ get_process_basic_info(PyObject* self, PyObject* args)
info.pr_nlwp, // no. of threads
info.pr_lwp.pr_state, // status code
info.pr_ttydev // tty nr
);
);
}
/*
* Return process name and args as a Python tuple.
*/
static PyObject*
get_process_name_and_args(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_name_and_args(PyObject *self, PyObject *args)
{
int pid;
char path[100];
@ -112,16 +117,15 @@ get_process_name_and_args(PyObject* self, PyObject* args)
sprintf(path, "/proc/%i/psinfo", pid);
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
return Py_BuildValue("ss", info.pr_fname,
info.pr_psargs);
return Py_BuildValue("ss", info.pr_fname, info.pr_psargs);
}
/*
* Return process user and system CPU times as a Python tuple.
*/
static PyObject*
get_process_cpu_times(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_cpu_times(PyObject *self, PyObject *args)
{
int pid;
char path[100];
@ -133,16 +137,17 @@ get_process_cpu_times(PyObject* self, PyObject* args)
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
// results are more precise than os.times()
return Py_BuildValue("dd", TV2DOUBLE(info.pr_utime),
TV2DOUBLE(info.pr_stime));
return Py_BuildValue("dd",
TV2DOUBLE(info.pr_utime),
TV2DOUBLE(info.pr_stime));
}
/*
* Return process uids/gids as a Python tuple.
*/
static PyObject*
get_process_cred(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_cred(PyObject *self, PyObject *args)
{
int pid;
char path[100];
@ -153,16 +158,17 @@ get_process_cred(PyObject* self, PyObject* args)
sprintf(path, "/proc/%i/cred", pid);
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
return Py_BuildValue("iiiiii", info.pr_ruid, info.pr_euid, info.pr_suid,
info.pr_rgid, info.pr_egid, info.pr_sgid);
return Py_BuildValue("iiiiii",
info.pr_ruid, info.pr_euid, info.pr_suid,
info.pr_rgid, info.pr_egid, info.pr_sgid);
}
/*
* Return process uids/gids as a Python tuple.
*/
static PyObject*
get_process_num_ctx_switches(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_num_ctx_switches(PyObject *self, PyObject *args)
{
int pid;
char path[100];
@ -189,7 +195,7 @@ get_process_num_ctx_switches(PyObject* self, PyObject* args)
* ...they should be meaningless anyway.
*
static PyObject*
get_process_io_counters(PyObject* self, PyObject* args)
proc_io_counters(PyObject* self, PyObject* args)
{
int pid;
char path[100];
@ -208,10 +214,11 @@ get_process_io_counters(PyObject* self, PyObject* args)
// 'pr_inblk' and 'pr_oublk' should be expressed in blocks of
// 8KB according to:
// http://www.brendangregg.com/Perf/paper_diskubyp1.pdf (pag. 8)
return Py_BuildValue("kkkk", info.pr_ioch,
info.pr_ioch,
info.pr_inblk,
info.pr_oublk);
return Py_BuildValue("kkkk",
info.pr_ioch,
info.pr_ioch,
info.pr_inblk,
info.pr_oublk);
}
*/
@ -219,8 +226,8 @@ get_process_io_counters(PyObject* self, PyObject* args)
/*
* Return information about a given process thread.
*/
static PyObject*
query_process_thread(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_query_thread(PyObject *self, PyObject *args)
{
int pid, tid;
char path[100];
@ -231,22 +238,24 @@ query_process_thread(PyObject* self, PyObject* args)
sprintf(path, "/proc/%i/lwp/%i/lwpstatus", pid, tid);
if (! psutil_file_to_struct(path, (void *)&info, sizeof(info)))
return NULL;
return Py_BuildValue("dd", TV2DOUBLE(info.pr_utime),
TV2DOUBLE(info.pr_stime));
return Py_BuildValue("dd",
TV2DOUBLE(info.pr_utime),
TV2DOUBLE(info.pr_stime));
}
/*
* Return information about system virtual memory.
*/
static PyObject*
get_swap_mem(PyObject* self, PyObject* args)
static PyObject *
psutil_swap_mem(PyObject *self, PyObject *args)
{
// XXX (arghhh!)
// total/free swap mem: commented out as for some reason I can't
// manage to get the same results shown by "swap -l", despite the
// code below is exactly the same as:
// http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/swap/swap.c
// http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/
// cmd/swap/swap.c
// We're going to parse "swap -l" output from Python (sigh!)
/*
@ -297,10 +306,10 @@ get_swap_mem(PyObject* self, PyObject* args)
return Py_BuildValue("(kk)", t, f);
*/
kstat_ctl_t *kc;
kstat_t *k;
cpu_stat_t *cpu;
int cpu_count = 0;
kstat_ctl_t *kc;
kstat_t *k;
cpu_stat_t *cpu;
int cpu_count = 0;
int flag = 0;
uint_t sin = 0;
uint_t sout = 0;
@ -311,12 +320,12 @@ get_swap_mem(PyObject* self, PyObject* args)
}
k = kc->kc_chain;
while (k != NULL) {
if((strncmp(k->ks_name, "cpu_stat", 8) == 0) && \
(kstat_read(kc, k, NULL) != -1) )
while (k != NULL) {
if ((strncmp(k->ks_name, "cpu_stat", 8) == 0) && \
(kstat_read(kc, k, NULL) != -1) )
{
flag = 1;
cpu = (cpu_stat_t*) k->ks_data;
cpu = (cpu_stat_t *) k->ks_data;
sin += cpu->cpu_vminfo.pgswapin; // num pages swapped in
sout += cpu->cpu_vminfo.pgswapout; // num pages swapped out
}
@ -335,8 +344,8 @@ get_swap_mem(PyObject* self, PyObject* args)
/*
* Return users currently connected on the system.
*/
static PyObject*
get_system_users(PyObject* self, PyObject* args)
static PyObject *
psutil_users(PyObject *self, PyObject *args)
{
struct utmpx *ut;
PyObject *ret_list = PyList_New(0);
@ -351,13 +360,13 @@ get_system_users(PyObject* self, PyObject* args)
user_proc = Py_True;
else
user_proc = Py_False;
tuple = Py_BuildValue("(sssfO)",
tuple = Py_BuildValue(
"(sssfO)",
ut->ut_user, // username
ut->ut_line, // tty
ut->ut_host, // hostname
(float)ut->ut_tv.tv_sec, // tstamp
user_proc // (bool) user process
);
user_proc); // (bool) user process
if (tuple == NULL)
goto error;
if (PyList_Append(ret_list, tuple))
@ -381,13 +390,13 @@ error:
* Return disk mounted partitions as a list of tuples including device,
* mount point and filesystem type.
*/
static PyObject*
get_disk_partitions(PyObject* self, PyObject* args)
static PyObject *
psutil_disk_partitions(PyObject *self, PyObject *args)
{
FILE *file;
struct mnttab mt;
PyObject* py_retlist = PyList_New(0);
PyObject* py_tuple = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
if (py_retlist == NULL)
return NULL;
@ -399,10 +408,12 @@ get_disk_partitions(PyObject* self, PyObject* args)
}
while (getmntent(file, &mt) == 0) {
py_tuple = Py_BuildValue("(ssss)", mt.mnt_special, // device
mt.mnt_mountp, // mount point
mt.mnt_fstype, // fs type
mt.mnt_mntopts); // options
py_tuple = Py_BuildValue(
"(ssss)",
mt.mnt_special, // device
mt.mnt_mountp, // mount point
mt.mnt_fstype, // fs type
mt.mnt_mntopts); // options
if (py_tuple == NULL)
goto error;
if (PyList_Append(py_retlist, py_tuple))
@ -425,16 +436,16 @@ error:
/*
* Return system-wide CPU times.
*/
static PyObject*
get_system_per_cpu_times(PyObject* self, PyObject* args)
static PyObject *
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;
PyObject *py_retlist = PyList_New(0);
PyObject *py_cputime = NULL;
if (py_retlist == NULL)
return NULL;
@ -446,7 +457,7 @@ get_system_per_cpu_times(PyObject* self, PyObject* args)
}
numcpus = sysconf(_SC_NPROCESSORS_ONLN) - 1;
for (i=0; i<=numcpus; i++) {
for (i = 0; i <= numcpus; i++) {
ksp = kstat_lookup(kc, "cpu_stat", i, NULL);
if (ksp == NULL) {
PyErr_SetFromErrno(PyExc_OSError);
@ -485,14 +496,14 @@ error:
/*
* Return disk IO statistics.
*/
static PyObject*
get_disk_io_counters(PyObject* self, PyObject* args)
static PyObject *
psutil_disk_io_counters(PyObject *self, PyObject *args)
{
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_io_t kio;
PyObject* py_retdict = PyDict_New();
PyObject* py_disk_info = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_disk_info = NULL;
if (py_retdict == NULL)
return NULL;
@ -509,18 +520,19 @@ get_disk_io_counters(PyObject* self, PyObject* args)
kstat_close(kc);
return PyErr_SetFromErrno(PyExc_OSError);;
}
py_disk_info = Py_BuildValue("(IIKKLL)",
kio.reads,
kio.writes,
kio.nread,
kio.nwritten,
kio.rtime / 1000 / 1000, // from nano to milli secs
kio.wtime / 1000 / 1000 // from nano to milli secs
py_disk_info = Py_BuildValue(
"(IIKKLL)",
kio.reads,
kio.writes,
kio.nread,
kio.nwritten,
kio.rtime / 1000 / 1000, // from nano to milli secs
kio.wtime / 1000 / 1000 // from nano to milli secs
);
if (!py_disk_info)
goto error;
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_disk_info))
if (PyDict_SetItemString(py_retdict, ksp->ks_name,
py_disk_info))
goto error;
Py_DECREF(py_disk_info);
}
@ -543,8 +555,8 @@ error:
/*
* Return process memory mappings.
*/
static PyObject*
get_process_memory_maps(PyObject* self, PyObject* args)
static PyObject *
psutil_proc_memory_maps(PyObject *self, PyObject *args)
{
int pid;
int fd = -1;
@ -561,8 +573,8 @@ get_process_memory_maps(PyObject* self, PyObject* args)
uintptr_t pr_addr_sz;
uintptr_t stk_base_sz, brk_base_sz;
PyObject* pytuple = NULL;
PyObject* py_retlist = PyList_New(0);
PyObject *pytuple = NULL;
PyObject *py_retlist = PyList_New(0);
if (py_retlist == NULL) {
return NULL;
@ -612,11 +624,11 @@ get_process_memory_maps(PyObject* self, PyObject* args)
// perms
sprintf(perms, "%c%c%c%c%c%c", p->pr_mflags & MA_READ ? 'r' : '-',
p->pr_mflags & MA_WRITE ? 'w' : '-',
p->pr_mflags & MA_EXEC ? 'x' : '-',
p->pr_mflags & MA_SHARED ? 's' : '-',
p->pr_mflags & MA_NORESERVE ? 'R' : '-',
p->pr_mflags & MA_RESERVED1 ? '*' : ' ');
p->pr_mflags & MA_WRITE ? 'w' : '-',
p->pr_mflags & MA_EXEC ? 'x' : '-',
p->pr_mflags & MA_SHARED ? 's' : '-',
p->pr_mflags & MA_NORESERVE ? 'R' : '-',
p->pr_mflags & MA_RESERVED1 ? '*' : ' ');
// name
if (strlen(p->pr_mapname) > 0) {
@ -630,7 +642,8 @@ get_process_memory_maps(PyObject* self, PyObject* args)
stk_base_sz = status.pr_stkbase + status.pr_stksize;
brk_base_sz = status.pr_brkbase + status.pr_brksize;
if ((pr_addr_sz > status.pr_stkbase) && (p->pr_vaddr < stk_base_sz)) {
if ((pr_addr_sz > status.pr_stkbase) &&
(p->pr_vaddr < stk_base_sz)) {
name = "[stack]";
}
else if ((p->pr_mflags & MA_ANON) && \
@ -645,13 +658,13 @@ get_process_memory_maps(PyObject* self, PyObject* args)
}
pytuple = Py_BuildValue("iisslll",
p->pr_vaddr,
pr_addr_sz,
perms,
name,
(long)p->pr_rss * p->pr_pagesize,
(long)p->pr_anon * p->pr_pagesize,
(long)p->pr_locked * p->pr_pagesize);
p->pr_vaddr,
pr_addr_sz,
perms,
name,
(long)p->pr_rss * p->pr_pagesize,
(long)p->pr_anon * p->pr_pagesize,
(long)p->pr_locked * p->pr_pagesize);
if (!pytuple)
goto error;
if (PyList_Append(py_retlist, pytuple))
@ -680,15 +693,15 @@ error:
/*
* Return a list of tuples for network I/O statistics.
*/
static PyObject*
get_net_io_counters(PyObject* self, PyObject* args)
static PyObject *
psutil_net_io_counters(PyObject *self, PyObject *args)
{
kstat_ctl_t *kc = NULL;
kstat_t *ksp;
kstat_named_t *rbytes, *wbytes, *rpkts, *wpkts, *ierrs, *oerrs;
PyObject* py_retdict = PyDict_New();
PyObject* py_ifc_info = NULL;
PyObject *py_retdict = PyDict_New();
PyObject *py_ifc_info = NULL;
if (py_retdict == NULL)
return NULL;
@ -726,30 +739,32 @@ get_net_io_counters(PyObject* self, PyObject* args)
oerrs = (kstat_named_t *)kstat_data_lookup(ksp, "oerrors");
if ((rbytes == NULL) || (wbytes == NULL) || (rpkts == NULL) ||
(wpkts == NULL) || (ierrs == NULL) || (oerrs == NULL))
(wpkts == NULL) || (ierrs == NULL) || (oerrs == NULL))
{
PyErr_SetString(PyExc_RuntimeError, "kstat_data_lookup() failed");
goto error;
}
#if defined(_INT64_TYPE)
py_ifc_info = Py_BuildValue("(KKKKkkii)", rbytes->value.ui64,
wbytes->value.ui64,
rpkts->value.ui64,
wpkts->value.ui64,
ierrs->value.ui32,
oerrs->value.ui32,
py_ifc_info = Py_BuildValue("(KKKKkkii)",
rbytes->value.ui64,
wbytes->value.ui64,
rpkts->value.ui64,
wpkts->value.ui64,
ierrs->value.ui32,
oerrs->value.ui32,
#else
py_ifc_info = Py_BuildValue("(kkkkkkii)", rbytes->value.ui32,
wbytes->value.ui32,
rpkts->value.ui32,
wpkts->value.ui32,
ierrs->value.ui32,
oerrs->value.ui32,
py_ifc_info = Py_BuildValue("(kkkkkkii)",
rbytes->value.ui32,
wbytes->value.ui32,
rpkts->value.ui32,
wpkts->value.ui32,
ierrs->value.ui32,
oerrs->value.ui32,
#endif
0, // dropin not supported
0 // dropout not supported
);
0, // dropin not supported
0 // dropout not supported
);
if (!py_ifc_info)
goto error;
if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info))
@ -757,8 +772,8 @@ get_net_io_counters(PyObject* self, PyObject* args)
Py_DECREF(py_ifc_info);
goto next;
next:
ksp = ksp->ks_next;
next:
ksp = ksp->ks_next;
}
kstat_close(kc);
@ -773,21 +788,26 @@ error:
}
#ifndef EXPER_IP_AND_ALL_IRES
#define EXPER_IP_AND_ALL_IRES (1024+4)
#endif
// a signaler for connections without an actual status
static int PSUTIL_CONN_NONE = 128;
/*
* Return TCP and UDP connections opened by process.
* UNIX sockets are excluded.
*
* Thanks to:
* https://github.com/DavidGriffith/finx/blob/master/nxsensor-3.5.0-1/src/sysdeps/solaris.c
* https://github.com/DavidGriffith/finx/blob/master/
* nxsensor-3.5.0-1/src/sysdeps/solaris.c
* ...and:
* https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/cmd-inet/usr.bin/netstat/netstat.c
* https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/
* cmd-inet/usr.bin/netstat/netstat.c
*/
static PyObject*
get_process_connections(PyObject* self, PyObject* args)
static PyObject *
psutil_net_connections(PyObject *self, PyObject *args)
{
long pid;
int sd = NULL;
@ -801,6 +821,7 @@ get_process_connections(PyObject* self, PyObject* args)
int i, flags, getcode, num_ent, state;
char lip[200], rip[200];
int lport, rport;
int processed_pid;
struct strbuf ctlbuf, databuf;
struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf;
struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf;
@ -873,22 +894,22 @@ get_process_connections(PyObject* self, PyObject* args)
getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags);
if (getcode != MOREDATA ||
ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
toa->PRIM_type != T_OPTMGMT_ACK ||
toa->MGMT_flags != T_SUCCESS)
ctlbuf.len < sizeof (struct T_optmgmt_ack) ||
toa->PRIM_type != T_OPTMGMT_ACK ||
toa->MGMT_flags != T_SUCCESS)
{
break;
break;
}
if (ctlbuf.len >= sizeof (struct T_error_ack) &&
tea->PRIM_type == T_ERROR_ACK)
tea->PRIM_type == T_ERROR_ACK)
{
PyErr_SetString(PyExc_RuntimeError, "ERROR_ACK");
goto error;
}
if (getcode == 0 &&
ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
toa->PRIM_type == T_OPTMGMT_ACK &&
toa->MGMT_flags == T_SUCCESS)
ctlbuf.len >= sizeof (struct T_optmgmt_ack) &&
toa->PRIM_type == T_OPTMGMT_ACK &&
toa->MGMT_flags == T_SUCCESS)
{
PyErr_SetString(PyExc_RuntimeError, "ERROR_T_OPTMGMT_ACK");
goto error;
@ -898,8 +919,6 @@ get_process_connections(PyObject* self, PyObject* args)
databuf.len = 0;
databuf.buf = (char *)malloc((int)mibhdr->len);
if (!databuf.buf) {
//perror("malloc");
//break;
PyErr_NoMemory();
goto error;
}
@ -916,8 +935,8 @@ get_process_connections(PyObject* self, PyObject* args)
tp = (mib2_tcpConnEntry_t *)databuf.buf;
num_ent = mibhdr->len / sizeof(mib2_tcpConnEntry_t);
for (i = 0; i < num_ent; i++, tp++) {
// check PID
if (tp->tcpConnCreationProcess != pid)
processed_pid = tp->tcpConnCreationProcess;
if (pid != -1 && processed_pid != pid)
continue;
// construct local/remote addresses
inet_ntop(AF_INET, &tp->tcpConnLocalAddress, lip, sizeof(lip));
@ -940,8 +959,9 @@ get_process_connections(PyObject* self, PyObject* args)
state = tp->tcpConnEntryInfo.ce_state;
// add item
py_tuple = Py_BuildValue("(iiiNNi)", -1, AF_INET, SOCK_STREAM,
py_laddr, py_raddr, state);
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM,
py_laddr, py_raddr, state,
processed_pid);
if (!py_tuple) {
goto error;
}
@ -952,13 +972,14 @@ get_process_connections(PyObject* self, PyObject* args)
}
#if defined(AF_INET6)
// TCPv6
else if (mibhdr->level == MIB2_TCP6 && mibhdr->name == MIB2_TCP6_CONN) {
else if (mibhdr->level == MIB2_TCP6 && mibhdr->name == MIB2_TCP6_CONN)
{
tp6 = (mib2_tcp6ConnEntry_t *)databuf.buf;
num_ent = mibhdr->len / sizeof(mib2_tcp6ConnEntry_t);
for (i = 0; i < num_ent; i++, tp6++) {
// check PID
if (tp6->tcp6ConnCreationProcess != pid)
processed_pid = tp6->tcp6ConnCreationProcess;
if (pid != -1 && processed_pid != pid)
continue;
// construct local/remote addresses
inet_ntop(AF_INET6, &tp6->tcp6ConnLocalAddress, lip, sizeof(lip));
@ -981,9 +1002,8 @@ get_process_connections(PyObject* self, PyObject* args)
state = tp6->tcp6ConnEntryInfo.ce_state;
// add item
py_tuple = Py_BuildValue("(iiiNNi)", -1, AF_INET6, SOCK_STREAM,
py_laddr, py_raddr, state);
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM,
py_laddr, py_raddr, state, processed_pid);
if (!py_tuple) {
goto error;
}
@ -993,12 +1013,20 @@ get_process_connections(PyObject* self, PyObject* args)
}
}
#endif
// UDPv4
else if (mibhdr->level == MIB2_UDP || mibhdr->level == MIB2_UDP_ENTRY) {
ude = (mib2_udpEntry_t *)databuf.buf;
num_ent = mibhdr->len / sizeof(mib2_udpEntry_t);
for (i = 0; i < num_ent; i++, ude++) {
// check PID
if (ude->udpCreationProcess != pid)
processed_pid = ude->udpCreationProcess;
if (pid != -1 && processed_pid != pid)
continue;
// XXX Very ugly hack! It seems we get here only the first
// time we bump into a UDPv4 socket. PID is a very high
// number (clearly impossible) and the address does not
// belong to any valid interface. Not sure what else
// to do other than skipping.
if (processed_pid > 131072)
continue;
inet_ntop(AF_INET, &ude->udpLocalAddress, lip, sizeof(lip));
lport = ude->udpLocalPort;
@ -1008,9 +1036,9 @@ get_process_connections(PyObject* self, PyObject* args)
py_raddr = Py_BuildValue("()");
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue("(iiiNNi)", -1, AF_INET, SOCK_DGRAM,
py_laddr, py_raddr,
PSUTIL_CONN_NONE);
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM,
py_laddr, py_raddr, PSUTIL_CONN_NONE,
processed_pid);
if (!py_tuple) {
goto error;
}
@ -1020,12 +1048,13 @@ get_process_connections(PyObject* self, PyObject* args)
}
}
#if defined(AF_INET6)
// UDPv6
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++) {
// check PID
if (ude6->udp6CreationProcess != pid)
processed_pid = ude6->udp6CreationProcess;
if (pid != -1 && processed_pid != pid)
continue;
inet_ntop(AF_INET6, &ude6->udp6LocalAddress, lip, sizeof(lip));
lport = ude6->udp6LocalPort;
@ -1035,9 +1064,9 @@ get_process_connections(PyObject* self, PyObject* args)
py_raddr = Py_BuildValue("()");
if (!py_raddr)
goto error;
py_tuple = Py_BuildValue("(iiiNNi)", -1, AF_INET6, SOCK_DGRAM,
py_laddr, py_raddr,
PSUTIL_CONN_NONE);
py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM,
py_laddr, py_raddr, PSUTIL_CONN_NONE,
processed_pid);
if (!py_tuple) {
goto error;
}
@ -1065,45 +1094,112 @@ error:
}
static PyObject *
psutil_boot_time(PyObject *self, PyObject *args)
{
float boot_time = 0.0;
struct utmpx *ut;
while (NULL != (ut = getutxent())) {
if (ut->ut_type == BOOT_TIME) {
boot_time = (float)ut->ut_tv.tv_sec;
break;
}
}
endutent();
if (boot_time != 0.0) {
return Py_BuildValue("f", boot_time);
}
else {
PyErr_SetString(PyExc_RuntimeError, "can't determine boot time");
return NULL;
}
}
/*
* Return the number of physical CPU cores on the system.
*/
static PyObject *
psutil_cpu_count_phys(PyObject *self, PyObject *args)
{
kstat_ctl_t *kc;
kstat_t *ksp;
int ncpus = 0;
kc = kstat_open();
if (kc == NULL)
goto error;
ksp = kstat_lookup(kc, "cpu_info", -1, NULL);
if (ksp == NULL)
goto error;
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)
goto error;
ncpus += 1;
}
kstat_close(kc);
if (ncpus > 0)
return Py_BuildValue("i", ncpus);
else
goto error;
error:
// mimic os.cpu_count()
if (kc != NULL)
kstat_close(kc);
Py_INCREF(Py_None);
return Py_None;
}
/*
* define the psutil C module methods and initialize the module.
*/
static PyMethodDef
PsutilMethods[] =
{
// --- process-related functions
{"get_process_basic_info", get_process_basic_info, METH_VARARGS,
"Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"},
{"get_process_name_and_args", get_process_name_and_args, METH_VARARGS,
"Return process name and args."},
{"get_process_cpu_times", get_process_cpu_times, METH_VARARGS,
"Return process user and system CPU times."},
{"get_process_cred", get_process_cred, METH_VARARGS,
"Return process uids/gids."},
{"query_process_thread", query_process_thread, METH_VARARGS,
"Return info about a process thread"},
{"get_process_memory_maps", get_process_memory_maps, METH_VARARGS,
"Return process memory mappings"},
{"get_process_num_ctx_switches", get_process_num_ctx_switches, METH_VARARGS,
"Return the number of context switches performed by process"},
{"get_process_connections", get_process_connections, METH_VARARGS,
"Return TCP and UDP connections opened by process."},
// --- process-related functions
{"proc_basic_info", psutil_proc_basic_info, METH_VARARGS,
"Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"},
{"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS,
"Return process name and args."},
{"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS,
"Return process user and system CPU times."},
{"proc_cred", psutil_proc_cred, METH_VARARGS,
"Return process uids/gids."},
{"query_process_thread", psutil_proc_query_thread, METH_VARARGS,
"Return info about a process thread"},
{"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS,
"Return process memory mappings"},
{"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS,
"Return the number of context switches performed by process"},
// --- system-related functions
{"get_swap_mem", get_swap_mem, METH_VARARGS,
"Return information about system swap memory."},
{"get_system_users", get_system_users, METH_VARARGS,
"Return currently connected users."},
{"get_disk_partitions", get_disk_partitions, METH_VARARGS,
"Return disk partitions."},
{"get_system_per_cpu_times", get_system_per_cpu_times, METH_VARARGS,
"Return system per-CPU times."},
{"get_disk_io_counters", get_disk_io_counters, METH_VARARGS,
"Return a Python dict of tuples for disk I/O statistics."},
{"get_net_io_counters", get_net_io_counters, METH_VARARGS,
"Return a Python dict of tuples for network I/O statistics."},
// --- system-related functions
{"swap_mem", psutil_swap_mem, METH_VARARGS,
"Return information about system swap memory."},
{"users", psutil_users, METH_VARARGS,
"Return currently connected users."},
{"disk_partitions", psutil_disk_partitions, METH_VARARGS,
"Return disk partitions."},
{"per_cpu_times", psutil_per_cpu_times, METH_VARARGS,
"Return system per-CPU times."},
{"disk_io_counters", psutil_disk_io_counters, METH_VARARGS,
"Return a Python dict of tuples for disk I/O statistics."},
{"net_io_counters", psutil_net_io_counters, METH_VARARGS,
"Return a Python dict of tuples for network I/O statistics."},
{"boot_time", psutil_boot_time, METH_VARARGS,
"Return system boot time in seconds since the EPOCH."},
{"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS,
"Return the number of physical CPUs on the system."},
{"net_connections", psutil_net_connections, METH_VARARGS,
"Return TCP and UDP syste-wide open connections."},
{NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
};
@ -1131,8 +1227,7 @@ psutil_sunos_clear(PyObject *m) {
return 0;
}
static struct PyModuleDef
moduledef = {
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"psutil_sunos",
NULL,
@ -1146,8 +1241,7 @@ moduledef = {
#define INITERROR return NULL
PyObject *
PyInit__psutil_sunos(void)
PyMODINIT_FUNC PyInit__psutil_sunos(void)
#else
#define INITERROR return
@ -1181,8 +1275,10 @@ void init_psutil_sunos(void)
PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2);
PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK);
PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT);
PyModule_AddIntConstant(module, "TCPS_IDLE", TCPS_IDLE); // sunos specific
PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND); // sunos specific
// sunos specific
PyModule_AddIntConstant(module, "TCPS_IDLE", TCPS_IDLE);
// sunos specific
PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND);
PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE);
if (module == NULL) {

View File

@ -1,29 +1,27 @@
/*
* $Id$
*
* 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.
*
* Sun OS specific module functions for _psutil_sunos extension
*/
#include <Python.h>
// processes
static PyObject* query_process_thread(PyObject* self, PyObject* args);
static PyObject* get_process_basic_info(PyObject* self, PyObject* args);
static PyObject* get_process_name_and_args(PyObject* self, PyObject* args);
static PyObject* get_process_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_process_cred(PyObject* self, PyObject* args);
static PyObject* get_process_memory_maps(PyObject* self, PyObject* args);
static PyObject* get_process_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* get_process_connections(PyObject* self, PyObject* args);
static PyObject* psutil_proc_basic_info(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_proc_cred(PyObject* self, PyObject* args);
static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args);
static PyObject* psutil_proc_name_and_args(PyObject* self, PyObject* args);
static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args);
static PyObject* psutil_proc_query_thread(PyObject* self, PyObject* args);
// system
static PyObject* get_swap_mem(PyObject* self, PyObject* args);
static PyObject* get_system_users(PyObject* self, PyObject* args);
static PyObject* get_disk_partitions(PyObject* self, PyObject* args);
static PyObject* get_system_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* get_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* get_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
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);

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <Python.h>
#include <windows.h>
// --- per-process functions
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_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_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);
static PyObject* psutil_proc_resume(PyObject* self, PyObject* args);
static PyObject* psutil_proc_suspend(PyObject* self, PyObject* args);
static PyObject* psutil_proc_threads(PyObject* self, PyObject* args);
static PyObject* psutil_proc_username(PyObject* self, PyObject* args);
static PyObject* psutil_proc_wait(PyObject* self, PyObject* args);
#if (PSUTIL_WINVER >= 0x0600) // Windows Vista
static PyObject* psutil_proc_io_priority_get(PyObject* self, PyObject* args);
static PyObject* psutil_proc_io_priority_set(PyObject* self, PyObject* args);
#endif
// --- system-related functions
static PyObject* psutil_boot_time(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args);
static PyObject* psutil_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args);
static PyObject* psutil_disk_usage(PyObject* self, PyObject* args);
static PyObject* psutil_net_connections(PyObject* self, PyObject* args);
static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args);
static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args);
static PyObject* psutil_pid_exists(PyObject* self, PyObject* args);
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);
// --- windows API bindings
static PyObject* psutil_win32_QueryDosDevice(PyObject* self, PyObject* args);
// --- internal
int psutil_proc_suspend_or_resume(DWORD pid, int suspend);

View File

@ -0,0 +1,490 @@
#!/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.
"""Windows platform implementation."""
import errno
import os
import sys
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
# 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",
]
# --- module level constants (gets pushed up to psutil module)
CONN_DELETE_TCB = "DELETE_TCB"
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES,
cext.ERROR_ACCESS_DENIED])
TCP_STATUSES = {
cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED,
cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT,
cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV,
cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1,
cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2,
cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT,
cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE,
cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT,
cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK,
cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN,
cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING,
cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB,
cext.PSUTIL_CONN_NONE: _common.CONN_NONE,
}
scputimes = namedtuple('scputimes', ['user', 'system', 'idle'])
svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free'])
pextmem = namedtuple(
'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool',
'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool',
'pagefile', 'peak_pagefile', 'private'])
pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss'])
pmmap_ext = namedtuple(
'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields))
# set later from __init__.py
NoSuchProcess = None
AccessDenied = None
TimeoutExpired = None
@lru_cache(maxsize=512)
def _win32_QueryDosDevice(s):
return cext.win32_QueryDosDevice(s)
def _convert_raw_path(s):
# convert paths using native DOS format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# into: "C:\Windows\systemew\file.txt"
if PY3 and not isinstance(s, str):
s = s.decode('utf8')
rawdrive = '\\'.join(s.split('\\')[:3])
driveletter = _win32_QueryDosDevice(rawdrive)
return os.path.join(driveletter, s[len(rawdrive):])
# --- public functions
def virtual_memory():
"""System virtual memory as a namedtuple."""
mem = cext.virtual_mem()
totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem
#
total = totphys
avail = availphys
free = availphys
used = total - avail
percent = usage_percent((total - avail), total, _round=1)
return svmem(total, avail, percent, used, free)
def swap_memory():
"""Swap system memory as a (total, used, free, sin, sout) tuple."""
mem = cext.virtual_mem()
total = mem[2]
free = mem[3]
used = total - free
percent = usage_percent(used, total, _round=1)
return _common.sswap(total, used, free, percent, 0, 0)
def disk_usage(path):
"""Return disk usage associated with path."""
try:
total, free = cext.disk_usage(path)
except WindowsError:
if not os.path.exists(path):
msg = "No such file or directory: '%s'" % path
raise OSError(errno.ENOENT, msg)
raise
used = total - free
percent = usage_percent(used, total, _round=1)
return _common.sdiskusage(total, used, free, percent)
def disk_partitions(all):
"""Return disk partitions."""
rawlist = cext.disk_partitions(all)
return [_common.sdiskpart(*x) for x in rawlist]
def cpu_times():
"""Return system CPU times as a named tuple."""
user, system, idle = cext.cpu_times()
return scputimes(user, system, idle)
def per_cpu_times():
"""Return system per-CPU times as a list of named tuples."""
ret = []
for cpu_t in cext.per_cpu_times():
user, system, idle = cpu_t
item = scputimes(user, system, idle)
ret.append(item)
return ret
def cpu_count_logical():
"""Return the number of logical CPUs in the system."""
return cext.cpu_count_logical()
def cpu_count_physical():
"""Return the number of physical CPUs in the system."""
return cext.cpu_count_phys()
def boot_time():
"""The system boot time expressed in seconds since the epoch."""
return cext.boot_time()
def net_connections(kind, _pid=-1):
"""Return socket connections. If pid == -1 return system-wide
connections (as opposed to connections opened by one process only).
"""
if kind not in conn_tmap:
raise ValueError("invalid %r kind argument; choose between %s"
% (kind, ', '.join([repr(x) for x in conn_tmap])))
families, types = conn_tmap[kind]
rawlist = cext.net_connections(_pid, families, types)
ret = []
for item in rawlist:
fd, fam, type, laddr, raddr, status, pid = item
status = TCP_STATUSES[status]
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)
return ret
def users():
"""Return currently connected users as a list of namedtuples."""
retlist = []
rawlist = cext.users()
for item in rawlist:
user, hostname, tstamp = item
nt = _common.suser(user, None, hostname, tstamp)
retlist.append(nt)
return retlist
pids = cext.pids
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
def wrap_exceptions(fun):
"""Decorator which translates bare OSError and WindowsError
exceptions into NoSuchProcess and AccessDenied.
"""
@wraps(fun)
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
# 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:
raise NoSuchProcess(self.pid, self._name)
raise
return wrapper
class Process(object):
"""Wrapper class around underlying C implementation."""
__slots__ = ["pid", "_name"]
def __init__(self, pid):
self.pid = pid
self._name = None
@wrap_exceptions
def name(self):
"""Return process name, which on Windows is always the final
part of the executable.
"""
# This is how PIDs 0 and 4 are always represented in taskmgr
# and process-hacker.
if self.pid == 0:
return "System Idle Process"
elif self.pid == 4:
return "System"
else:
return os.path.basename(self.exe())
@wrap_exceptions
def exe(self):
# Note: os.path.exists(path) may return False even if the file
# is there, see:
# http://stackoverflow.com/questions/3112546/os-path-exists-lies
# see https://github.com/giampaolo/psutil/issues/414
# see https://github.com/giampaolo/psutil/issues/528
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
return _convert_raw_path(cext.proc_exe(self.pid))
@wrap_exceptions
def cmdline(self):
return cext.proc_cmdline(self.pid)
def ppid(self):
try:
return ppid_map()[self.pid]
except KeyError:
raise NoSuchProcess(self.pid, self._name)
def _get_raw_meminfo(self):
try:
return cext.proc_memory_info(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return cext.proc_memory_info_2(self.pid)
raise
@wrap_exceptions
def memory_info(self):
# on Windows RSS == WorkingSetSize and VSM == PagefileUsage
# fields of PROCESS_MEMORY_COUNTERS struct:
# http://msdn.microsoft.com/en-us/library/windows/desktop/
# ms684877(v=vs.85).aspx
t = self._get_raw_meminfo()
return _common.pmem(t[2], t[7])
@wrap_exceptions
def memory_info_ex(self):
return pextmem(*self._get_raw_meminfo())
def memory_maps(self):
try:
raw = cext.proc_memory_maps(self.pid)
except OSError:
# 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:
raise NoSuchProcess(self.pid, self._name)
raise
else:
for addr, perm, path, rss in raw:
path = _convert_raw_path(path)
addr = hex(addr)
yield (addr, perm, path, rss)
@wrap_exceptions
def kill(self):
return cext.proc_kill(self.pid)
@wrap_exceptions
def wait(self, timeout=None):
if timeout is None:
timeout = cext.INFINITE
else:
# WaitForSingleObject() expects time in milliseconds
timeout = int(timeout * 1000)
ret = cext.proc_wait(self.pid, timeout)
if ret == WAIT_TIMEOUT:
# support for private module import
if TimeoutExpired is None:
raise RuntimeError("timeout expired")
raise TimeoutExpired(timeout, self.pid, self._name)
return ret
@wrap_exceptions
def username(self):
if self.pid in (0, 4):
return 'NT AUTHORITY\\SYSTEM'
return cext.proc_username(self.pid)
@wrap_exceptions
def create_time(self):
# special case for kernel process PIDs; return system boot time
if self.pid in (0, 4):
return boot_time()
try:
return cext.proc_create_time(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return cext.proc_create_time_2(self.pid)
raise
@wrap_exceptions
def num_threads(self):
return cext.proc_num_threads(self.pid)
@wrap_exceptions
def threads(self):
rawlist = cext.proc_threads(self.pid)
retlist = []
for thread_id, utime, stime in rawlist:
ntuple = _common.pthread(thread_id, utime, stime)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def cpu_times(self):
try:
ret = cext.proc_cpu_times(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_cpu_times_2(self.pid)
else:
raise
return _common.pcputimes(*ret)
@wrap_exceptions
def suspend(self):
return cext.proc_suspend(self.pid)
@wrap_exceptions
def resume(self):
return cext.proc_resume(self.pid)
@wrap_exceptions
def cwd(self):
if self.pid in (0, 4):
raise AccessDenied(self.pid, self._name)
# return a normalized pathname since the native C function appends
# "\\" at the and of the path
path = cext.proc_cwd(self.pid)
return os.path.normpath(path)
@wrap_exceptions
def open_files(self):
if self.pid in (0, 4):
return []
retlist = []
# Filenames come in in native format like:
# "\Device\HarddiskVolume1\Windows\systemew\file.txt"
# 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)
retlist.append(ntuple)
return retlist
@wrap_exceptions
def connections(self, kind='inet'):
return net_connections(kind, _pid=self.pid)
@wrap_exceptions
def nice_get(self):
return cext.proc_priority_get(self.pid)
@wrap_exceptions
def nice_set(self, value):
return cext.proc_priority_set(self.pid, value)
# available on Windows >= Vista
if hasattr(cext, "proc_io_priority_get"):
@wrap_exceptions
def ionice_get(self):
return cext.proc_io_priority_get(self.pid)
@wrap_exceptions
def ionice_set(self, value, _):
if _:
raise TypeError("set_proc_ionice() on Windows takes only "
"1 argument (2 given)")
if value not in (2, 1, 0):
raise ValueError("value must be 2 (normal), 1 (low) or 0 "
"(very low); got %r" % value)
return cext.proc_io_priority_set(self.pid, value)
@wrap_exceptions
def io_counters(self):
try:
ret = cext.proc_io_counters(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
ret = cext.proc_io_counters_2(self.pid)
else:
raise
return _common.pio(*ret)
@wrap_exceptions
def status(self):
suspended = cext.proc_is_suspended(self.pid)
if suspended:
return _common.STATUS_STOPPED
else:
return _common.STATUS_RUNNING
@wrap_exceptions
def cpu_affinity_get(self):
from_bitmask = lambda x: [i for i in xrange(64) if (1 << i) & x]
bitmask = cext.proc_cpu_affinity_get(self.pid)
return from_bitmask(bitmask)
@wrap_exceptions
def cpu_affinity_set(self, value):
def to_bitmask(l):
if not l:
raise ValueError("invalid argument %r" % l)
out = 0
for b in l:
out |= 2 ** b
return out
# SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER
# is returned for an invalid CPU but this seems not to be true,
# therefore we check CPUs validy beforehand.
allcpus = list(range(len(per_cpu_times())))
for cpu in value:
if cpu not in allcpus:
raise ValueError("invalid CPU %r" % cpu)
bitmask = to_bitmask(value)
cext.proc_cpu_affinity_set(self.pid, bitmask)
@wrap_exceptions
def num_handles(self):
try:
return cext.proc_num_handles(self.pid)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
return cext.proc_num_handles_2(self.pid)
raise
@wrap_exceptions
def num_ctx_switches(self):
tupl = cext.proc_num_ctx_switches(self.pid)
return _common.pctxsw(*tupl)

View File

@ -3,10 +3,11 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by _psutil_bsd
* module methods.
* Helper functions related to fetching process information.
* Used by _psutil_bsd module methods.
*/
#include <Python.h>
#include <assert.h>
#include <errno.h>
@ -35,7 +36,7 @@ int
psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount)
{
int err;
struct kinfo_proc * result;
struct kinfo_proc *result;
int done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 };
// Declaring name as const requires us to cast it when passing it to
@ -82,7 +83,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount)
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length, NULL, 0);
result, &length, NULL, 0);
if (err == -1)
err = errno;
if (err == 0) {
@ -114,7 +115,7 @@ psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount)
char
*psutil_get_cmd_path(long pid, size_t *pathsize)
{
int mib[4];
int mib[4];
char *path;
size_t size = 0;
@ -140,7 +141,7 @@ char
*pathsize = size;
if (sysctl(mib, 4, path, &size, NULL, 0) == -1) {
free(path);
return NULL; /* Insufficient privileges */
return NULL; // Insufficient privileges
}
return path;
@ -167,7 +168,7 @@ char
size_t size = sizeof(argmax);
char *procargs = NULL;
/* Get the maximum process arguments size. */
// Get the maximum process arguments size.
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
@ -175,7 +176,7 @@ char
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
return NULL;
/* Allocate space for the arguments. */
// Allocate space for the arguments.
procargs = (char *)malloc(argmax);
if (procargs == NULL) {
PyErr_NoMemory();
@ -193,7 +194,7 @@ char
size = argmax;
if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) {
free(procargs);
return NULL; /* Insufficient privileges */
return NULL; // Insufficient privileges
}
// return string and set the length of arguments
@ -202,8 +203,8 @@ char
}
/* returns the command line as a python list object */
PyObject*
// returns the command line as a python list object
PyObject *
psutil_get_arg_list(long pid)
{
char *argstr = NULL;
@ -225,7 +226,7 @@ psutil_get_arg_list(long pid)
// arguments add each string to the list then step forward to the next
// separator
if (argsize > 0) {
while(pos < argsize) {
while (pos < argsize) {
item = Py_BuildValue("s", &argstr[pos]);
if (!item)
goto error;

View File

@ -2,17 +2,14 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by _psutil_bsd
* module methods.
*/
#include <Python.h>
typedef struct kinfo_proc kinfo_proc;
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
char *psutil_get_cmd_args(long pid, size_t *argsize);
char *psutil_get_cmd_path(long pid, size_t *pathsize);
int psutil_pid_exists(long pid);
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
int psutil_pid_exists(long pid);
PyObject* psutil_get_arg_list(long pid);

View File

@ -3,14 +3,15 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by _psutil_osx
* module methods.
* Helper functions related to fetching process information.
* Used by _psutil_osx module methods.
*/
#include <Python.h>
#include <assert.h>
#include <errno.h>
#include <limits.h> /* for INT_MAX */
#include <limits.h> // for INT_MAX
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
@ -46,7 +47,6 @@ psutil_pid_exists(long pid)
}
/*
* Returns a list of all BSD processes on the system. This routine
* allocates the list and puts it in *procList and a count of the
@ -58,12 +58,12 @@ psutil_pid_exists(long pid)
int
psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
{
/* Declaring mib as const requires use of a cast since the
* sysctl prototype doesn't include the const modifier. */
// Declaring mib as const requires use of a cast since the
// sysctl prototype doesn't include the const modifier.
static const int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
size_t size, size2;
void *ptr;
int err, lim = 8; /* some limit */
int err, lim = 8; // some limit
assert( procList != NULL);
assert(*procList == NULL);
@ -71,7 +71,8 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
*procCount = 0;
/* We start by calling sysctl with ptr == NULL and size == 0.
/*
* We start by calling sysctl with ptr == NULL and size == 0.
* That will succeed, and set size to the appropriate length.
* We then allocate a buffer of at least that size and call
* sysctl with that buffer. If that succeeds, we're done.
@ -88,7 +89,7 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
return errno;
}
size2 = size + (size >> 3); /* add some */
size2 = size + (size >> 3); // add some
if (size2 > size) {
ptr = malloc(size2);
if (ptr == NULL) {
@ -121,7 +122,7 @@ psutil_get_proc_list(kinfo_proc **procList, size_t *procCount)
}
/* Read the maximum argument size for processes */
// Read the maximum argument size for processes
int
psutil_get_argmax()
{
@ -136,8 +137,8 @@ psutil_get_argmax()
}
/* return process args as a python list */
PyObject*
// return process args as a python list
PyObject *
psutil_get_arg_list(long pid)
{
int mib[3];
@ -151,12 +152,12 @@ psutil_get_arg_list(long pid)
PyObject *arg = NULL;
PyObject *arglist = NULL;
//special case for PID 0 (kernel_task) where cmdline cannot be fetched
// special case for PID 0 (kernel_task) where cmdline cannot be fetched
if (pid == 0) {
return Py_BuildValue("[]");
}
/* read argmax and allocate memory for argument space. */
// read argmax and allocate memory for argument space.
argmax = psutil_get_argmax();
if (! argmax) {
PyErr_SetFromErrno(PyExc_OSError);
@ -169,12 +170,13 @@ psutil_get_arg_list(long pid)
goto error;
}
/* read argument space */
// read argument space
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = pid;
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
if (EINVAL == errno) { // invalid == access denied OR nonexistent PID
if (EINVAL == errno) {
// EINVAL == access denied OR nonexistent PID
if ( psutil_pid_exists(pid) ) {
AccessDenied();
} else {
@ -185,7 +187,7 @@ psutil_get_arg_list(long pid)
}
arg_end = &procargs[argmax];
/* copy the number of arguments to nargs */
// copy the number of arguments to nargs
memcpy(&nargs, procargs, sizeof(nargs));
arg_ptr = procargs + sizeof(nargs);
@ -204,7 +206,7 @@ psutil_get_arg_list(long pid)
}
}
/* iterate through arguments */
// iterate through arguments
curr_arg = arg_ptr;
arglist = Py_BuildValue("[]");
if (!arglist)
@ -255,9 +257,7 @@ psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
return -1;
}
/*
* sysctl succeeds but len is zero, happens when process has gone away
*/
// sysctl succeeds but len is zero, happens when process has gone away
if (len == 0) {
NoSuchProcess();
return -1;

View File

@ -2,19 +2,15 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by _psutil_osx
* module methods.
*/
#include <Python.h>
typedef struct kinfo_proc kinfo_proc;
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
int psutil_get_argmax(void);
int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
int psutil_pid_exists(long pid);
int psutil_proc_pidinfo(long pid, int flavor, void *pti, int size);
PyObject* psutil_get_arg_list(long pid);

View File

@ -0,0 +1,41 @@
// mingw headers are missing this
typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP {
RelationProcessorCore,
RelationNumaNode,
RelationCache,
RelationProcessorPackage,
RelationGroup,
RelationAll=0xffff
} LOGICAL_PROCESSOR_RELATIONSHIP;
typedef enum _PROCESSOR_CACHE_TYPE {
CacheUnified,CacheInstruction,CacheData,CacheTrace
} PROCESSOR_CACHE_TYPE;
typedef struct _CACHE_DESCRIPTOR {
BYTE Level;
BYTE Associativity;
WORD LineSize;
DWORD Size;
PROCESSOR_CACHE_TYPE Type;
} CACHE_DESCRIPTOR,*PCACHE_DESCRIPTOR;
typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
ULONG_PTR ProcessorMask;
LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
union {
struct {
BYTE Flags;
} ProcessorCore;
struct {
DWORD NodeNumber;
} NumaNode;
CACHE_DESCRIPTOR Cache;
ULONGLONG Reserved[2];
};
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION,*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;
WINBASEAPI WINBOOL WINAPI
GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
PDWORD ReturnedLength);

View File

@ -2,11 +2,9 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
*/
typedef enum _KTHREAD_STATE
{
typedef enum _KTHREAD_STATE {
Initialized,
Ready,
Running,
@ -19,8 +17,7 @@ typedef enum _KTHREAD_STATE
MaximumThreadState
} KTHREAD_STATE, *PKTHREAD_STATE;
typedef enum _KWAIT_REASON
{
typedef enum _KWAIT_REASON {
Executive = 0,
FreePage = 1,
PageIn = 2,
@ -61,9 +58,7 @@ typedef enum _KWAIT_REASON
MaximumWaitReason = 37
} KWAIT_REASON, *PKWAIT_REASON;
typedef struct _CLIENT_ID
{
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
@ -75,9 +70,7 @@ typedef struct _UNICODE_STRING {
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION
{
typedef struct _SYSTEM_TIMEOFDAY_INFORMATION {
LARGE_INTEGER BootTime;
LARGE_INTEGER CurrentTime;
LARGE_INTEGER TimeZoneBias;
@ -87,8 +80,7 @@ typedef struct _SYSTEM_TIMEOFDAY_INFORMATION
ULONGLONG SleepTimeBias;
} SYSTEM_TIMEOFDAY_INFORMATION, *PSYSTEM_TIMEOFDAY_INFORMATION;
typedef struct _SYSTEM_THREAD_INFORMATION
{
typedef struct _SYSTEM_THREAD_INFORMATION {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
@ -105,8 +97,7 @@ typedef struct _SYSTEM_THREAD_INFORMATION
typedef struct _TEB *PTEB;
// private
typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION
{
typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION {
SYSTEM_THREAD_INFORMATION ThreadInfo;
PVOID StackBase;
PVOID StackLimit;
@ -117,8 +108,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_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
@ -163,7 +153,8 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION,
*PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef enum _SYSTEM_INFORMATION_CLASS {
@ -180,7 +171,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
// ================================================
// get_system_users support ()
// psutil.users() support
// ================================================
typedef struct _WINSTATION_INFO {
@ -208,7 +199,7 @@ typedef struct _WINSTATIONINFORMATIONW {
BYTE Reserved3[1140];
} WINSTATIONINFORMATIONW, *PWINSTATIONINFORMATIONW;
// start mingw support:
// mingw support:
// http://www.koders.com/c/fid7C02CAE627C526914CDEB427405B51DF393A5EFA.aspx
#ifndef _INC_WTSAPI
typedef struct _WTS_CLIENT_ADDRESS {
@ -216,19 +207,11 @@ typedef struct _WTS_CLIENT_ADDRESS {
BYTE Address[20]; // client network address
} WTS_CLIENT_ADDRESS, * PWTS_CLIENT_ADDRESS;
HANDLE
WINAPI
WTSOpenServerA(
IN LPSTR pServerName
);
HANDLE WINAPI WTSOpenServerA(IN LPSTR pServerName);
VOID
WINAPI
WTSCloseServer(
IN HANDLE hServer
);
VOID WINAPI WTSCloseServer(IN HANDLE hServer);
#endif
// end mingw support:
/*
* NtQueryInformationProcess code taken from
@ -243,7 +226,7 @@ typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength
);
);
typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
HANDLE ProcessHandle,
@ -252,8 +235,7 @@ typedef NTSTATUS (NTAPI *_NtSetInformationProcess)(
DWORD ProcessInformationLength
);
typedef struct _PROCESS_BASIC_INFORMATION
{
typedef struct _PROCESS_BASIC_INFORMATION {
PVOID Reserved1;
PVOID PebBaseAddress;
PVOID Reserved2[2];
@ -261,7 +243,6 @@ typedef struct _PROCESS_BASIC_INFORMATION
PVOID Reserved3;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation,
ProcessQuotaLimits,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* 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.
*
@ -15,7 +15,7 @@
#include "process_handles.h"
#ifndef NT_SUCCESS
#define NT_SUCCESS(x) ((x) >= 0)
#define NT_SUCCESS(x) ((x) >= 0)
#endif
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
@ -28,9 +28,9 @@
typedef LONG NTSTATUS;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
@ -38,7 +38,7 @@ typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
);
typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
HANDLE SourceProcessHandle,
@ -48,7 +48,7 @@ typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
ACCESS_MASK DesiredAccess,
ULONG Attributes,
ULONG Options
);
);
typedef NTSTATUS (NTAPI *_NtQueryObject)(
HANDLE ObjectHandle,
@ -56,10 +56,9 @@ typedef NTSTATUS (NTAPI *_NtQueryObject)(
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
);
);
typedef struct _SYSTEM_HANDLE
{
typedef struct _SYSTEM_HANDLE {
ULONG ProcessId;
BYTE ObjectTypeNumber;
BYTE Flags;
@ -68,14 +67,12 @@ typedef struct _SYSTEM_HANDLE
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
typedef struct _SYSTEM_HANDLE_INFORMATION {
ULONG HandleCount;
SYSTEM_HANDLE Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef enum _POOL_TYPE
{
typedef enum _POOL_TYPE {
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
@ -85,8 +82,7 @@ typedef enum _POOL_TYPE
NonPagedPoolCacheAlignedMustS
} POOL_TYPE, *PPOOL_TYPE;
typedef struct _OBJECT_TYPE_INFORMATION
{
typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING Name;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
@ -111,26 +107,25 @@ typedef struct _OBJECT_TYPE_INFORMATION
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
PVOID
GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
{
return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
}
PyObject*
PyObject *
psutil_get_open_files(long pid, HANDLE processHandle)
{
_NtQuerySystemInformation NtQuerySystemInformation =
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
_NtDuplicateObject NtDuplicateObject =
GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
_NtQueryObject NtQueryObject =
GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
NTSTATUS status;
PSYSTEM_HANDLE_INFORMATION handleInfo;
ULONG handleInfoSize = 0x10000;
ULONG i;
ULONG fileNameLength;
PyObject *filesList = Py_BuildValue("[]");
@ -147,76 +142,90 @@ psutil_get_open_files(long pid, HANDLE processHandle)
return NULL;
}
/* NtQuerySystemInformation won't give us the correct buffer size,
so we guess by doubling the buffer size. */
// 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)
SystemHandleInformation,
handleInfo,
handleInfoSize,
NULL
)) == STATUS_INFO_LENGTH_MISMATCH)
{
handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
handleInfo = (PSYSTEM_HANDLE_INFORMATION) \
realloc(handleInfo, handleInfoSize *= 2);
}
/* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
// NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH
if (!NT_SUCCESS(status)) {
//printf("NtQuerySystemInformation failed!\n");
Py_DECREF(filesList);
free(handleInfo);
return NULL;
}
for (i = 0; i < handleInfo->HandleCount; i++)
{
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;
/* Check if this handle belongs to the PID the user specified. */
// Check if this handle belongs to the PID the user specified.
if (handle.ProcessId != pid)
continue;
/* 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)) {
// 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;
}
/* Duplicate the handle so we can query it. */
if (!NT_SUCCESS(NtDuplicateObject(
processHandle,
handle.Handle,
GetCurrentProcess(),
&dupHandle,
0,
0,
0
)))
{
//printf("[%#x] Error!\n", handle.Handle);
continue;
}
if (!DuplicateHandle(processHandle,
handle.Handle,
GetCurrentProcess(),
&dupHandle,
0,
TRUE,
DUPLICATE_SAME_ACCESS))
{
//printf("[%#x] Error: %d \n", handle.Handle, GetLastError());
continue;
}
/* Query the object type. */
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;
}
}
CloseHandle(mapHandle);
// Query the object type.
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectTypeInformation,
objectTypeInfo,
0x1000,
NULL
)))
dupHandle,
ObjectTypeInformation,
objectTypeInfo,
0x1000,
NULL
)))
{
//printf("[%#x] Error!\n", handle.Handle);
free(objectTypeInfo);
CloseHandle(dupHandle);
continue;
@ -224,24 +233,24 @@ psutil_get_open_files(long pid, HANDLE processHandle)
objectNameInfo = malloc(0x1000);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
0x1000,
&returnLength
)))
dupHandle,
ObjectNameInformation,
objectNameInfo,
0x1000,
&returnLength
)))
{
/* Reallocate the buffer and try again. */
// Reallocate the buffer and try again.
objectNameInfo = realloc(objectNameInfo, returnLength);
if (!NT_SUCCESS(NtQueryObject(
dupHandle,
ObjectNameInformation,
objectNameInfo,
returnLength,
NULL
)))
dupHandle,
ObjectNameInformation,
objectNameInfo,
returnLength,
NULL
)))
{
/* We have the type name, so just display that.*/
// We have the type name, so just display that.
/*
printf(
"[%#x] %.*S: (could not get name)\n",
@ -258,26 +267,28 @@ psutil_get_open_files(long pid, HANDLE processHandle)
}
}
/* Cast our buffer into an UNICODE_STRING. */
// Cast our buffer into an UNICODE_STRING.
objectName = *(PUNICODE_STRING)objectNameInfo;
/* Print the information! */
// Print the information!
if (objectName.Length)
{
/* The object has a name. Make sure it is a file otherwise
ignore it */
// 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);
// 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 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);
@ -299,7 +310,7 @@ psutil_get_open_files(long pid, HANDLE processHandle)
}
else
{
/* Print something else. */
// Print something else.
/*
printf(
"[%#x] %.*S: (unnamed)\n",

View File

@ -1,6 +1,4 @@
/*
* $Id: process_info.h 1060 2011-07-02 18:05:26Z g.rodola $
*
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.

View File

@ -4,7 +4,7 @@
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by
* _psutil_mswindows module methods.
* _psutil_windows module methods.
*/
#include <Python.h>
@ -15,7 +15,7 @@
#include "security.h"
#include "process_info.h"
#include "ntextapi.h"
#include "../../_psutil_common.h"
/*
@ -29,7 +29,7 @@ HANDLE
psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
{
HANDLE hProcess;
DWORD processExitCode = 0;
DWORD processExitCode = 0;
if (pid == 0) {
// otherwise we'd get NoSuchProcess
@ -47,7 +47,7 @@ psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
return NULL;
}
/* make sure the process is running */
// make sure the process is running
GetExitCodeProcess(hProcess, &processExitCode);
if (processExitCode == 0) {
NoSuchProcess();
@ -76,7 +76,7 @@ psutil_get_peb_address(HANDLE ProcessHandle)
{
_NtQueryInformationProcess NtQueryInformationProcess =
(_NtQueryInformationProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi;
NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL);
@ -84,12 +84,12 @@ psutil_get_peb_address(HANDLE ProcessHandle)
}
DWORD*
DWORD *
psutil_get_pids(DWORD *numberOfReturnedPIDs) {
/* Win32 SDK says the only way to know if our process array
* wasn't large enough is to check the returned size and make
* sure that it doesn't match the size of the array.
* If it does we allocate a larger array and try again */
// Win32 SDK says the only way to know if our process array
// wasn't large enough is to check the returned size and make
// sure that it doesn't match the size of the array.
// If it does we allocate a larger array and try again
// Stores the actual array
DWORD *procArray = NULL;
@ -113,7 +113,7 @@ psutil_get_pids(DWORD *numberOfReturnedPIDs) {
PyErr_SetFromWindowsErr(0);
return NULL;
}
} while(enumReturnSz == procArraySz * sizeof(DWORD));
} while (enumReturnSz == procArraySz * sizeof(DWORD));
// The number of elements is the returned size / size of each element
*numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD);
@ -162,7 +162,8 @@ psutil_pid_is_running(DWORD pid)
return (exitCode == STILL_ACTIVE);
}
// access denied means there's a process there so we'll assume it's running
// access denied means there's a process there so we'll assume
// it's running
if (GetLastError() == ERROR_ACCESS_DENIED) {
CloseHandle(hProcess);
return 1;
@ -216,66 +217,11 @@ handlep_is_running(HANDLE hProcess)
}
// Return None to represent NoSuchProcess, else return NULL for
// other exception or the name as a Python string
PyObject*
psutil_get_name(long pid)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if( Process32First(h, &pe)) {
do {
if (pe.th32ProcessID == pid) {
CloseHandle(h);
return Py_BuildValue("s", pe.szExeFile);
}
} while(Process32Next(h, &pe));
// the process was never found, set NoSuchProcess exception
NoSuchProcess();
CloseHandle(h);
return NULL;
}
CloseHandle(h);
return PyErr_SetFromWindowsErr(0);
}
/* returns parent pid (as a Python int) for given pid or None on failure */
PyObject*
psutil_get_ppid(long pid)
{
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if( Process32First(h, &pe)) {
do {
if (pe.th32ProcessID == pid) {
CloseHandle(h);
return Py_BuildValue("I", pe.th32ParentProcessID);
}
} while(Process32Next(h, &pe));
// the process was never found, set NoSuchProcess exception
NoSuchProcess();
CloseHandle(h);
return NULL;
}
CloseHandle(h);
return PyErr_SetFromWindowsErr(0);
}
/*
* returns a Python list representing the arguments for the process
* with given pid or NULL on error.
*/
PyObject*
PyObject *
psutil_get_arg_list(long pid)
{
int nArgs, i;
@ -290,19 +236,19 @@ 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 */
// get the address of ProcessParameters
#ifdef _WIN64
if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32,
&rtlUserProcParamsAddress, sizeof(PVOID), NULL))
&rtlUserProcParamsAddress, sizeof(PVOID), NULL))
#else
if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10,
&rtlUserProcParamsAddress, sizeof(PVOID), NULL))
&rtlUserProcParamsAddress, sizeof(PVOID), NULL))
#endif
{
////printf("Could not read the address of ProcessParameters!\n");
@ -310,46 +256,42 @@ psutil_get_arg_list(long pid)
goto error;
}
/* read the CommandLine UNICODE_STRING structure */
// read the CommandLine UNICODE_STRING structure
#ifdef _WIN64
if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112,
&commandLine, sizeof(commandLine), NULL))
&commandLine, sizeof(commandLine), NULL))
#else
if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40,
&commandLine, sizeof(commandLine), NULL))
&commandLine, sizeof(commandLine), NULL))
#endif
{
////printf("Could not read CommandLine!\n");
PyErr_SetFromWindowsErr(0);
goto error;
}
/* allocate memory to hold the command line */
commandLineContents = (WCHAR *)malloc(commandLine.Length+1);
// allocate memory to hold the command line
commandLineContents = (WCHAR *)malloc(commandLine.Length + 1);
if (commandLineContents == NULL) {
PyErr_NoMemory();
goto error;
}
/* read the command line */
// read the command line
if (!ReadProcessMemory(hProcess, commandLine.Buffer,
commandLineContents, commandLine.Length, NULL))
commandLineContents, commandLine.Length, NULL))
{
////printf("Could not read the command line string!\n");
PyErr_SetFromWindowsErr(0);
goto error;
}
/* print the commandline */
////printf("%.*S\n", commandLine.Length / 2, commandLineContents);
// Null-terminate the string to prevent wcslen from returning
// incorrect length the length specifier is in characters, but
// commandLine.Length is in bytes.
commandLineContents[(commandLine.Length / sizeof(WCHAR))] = '\0';
// null-terminate the string to prevent wcslen from returning incorrect length
// the length specifier is in characters, but commandLine.Length is in bytes
commandLineContents[(commandLine.Length/sizeof(WCHAR))] = '\0';
// attemempt tp parse the command line using Win32 API, fall back on string
// cmdline version otherwise
// attempt tp parse the command line using Win32 API, fall back
// on string cmdline version otherwise
szArglist = CommandLineToArgvW(commandLineContents, &nArgs);
if (NULL == szArglist) {
// failed to parse arglist
@ -358,35 +300,32 @@ psutil_get_arg_list(long pid)
commandLine.Length / 2);
if (arg_from_wchar == NULL)
goto error;
#if PY_MAJOR_VERSION >= 3
argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar));
#else
argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar));
#endif
#if PY_MAJOR_VERSION >= 3
argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar));
#else
argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar));
#endif
if (!argList)
goto error;
}
else {
// arglist parsed as array of UNICODE_STRING, so convert each to Python
// string object and add to arg list
// arglist parsed as array of UNICODE_STRING, so convert each to
// Python string object and add to arg list
argList = Py_BuildValue("[]");
if (argList == NULL)
goto error;
for(i=0; i<nArgs; i++) {
for (i = 0; i < nArgs; i++) {
arg_from_wchar = NULL;
arg = NULL;
////printf("%d: %.*S (%d characters)\n", i, wcslen(szArglist[i]),
// szArglist[i], wcslen(szArglist[i]));
arg_from_wchar = PyUnicode_FromWideChar(szArglist[i],
wcslen(szArglist[i])
);
wcslen(szArglist[i]));
if (arg_from_wchar == NULL)
goto error;
#if PY_MAJOR_VERSION >= 3
arg = PyUnicode_FromObject(arg_from_wchar);
#else
arg = PyUnicode_AsUTF8String(arg_from_wchar);
#endif
#if PY_MAJOR_VERSION >= 3
arg = PyUnicode_FromObject(arg_from_wchar);
#else
arg = PyUnicode_AsUTF8String(arg_from_wchar);
#endif
if (arg == NULL)
goto error;
Py_XDECREF(arg_from_wchar);
@ -417,16 +356,14 @@ error:
#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes))
#define PH_NEXT_PROCESS(Process) ( \
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
(PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \
NULL \
)
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \
(PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \
((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \
NULL)
const STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
const STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
const int STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
const int STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
/*
* Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure
@ -434,7 +371,8 @@ const STATUS_BUFFER_TOO_SMALL = 0xC0000023L;
* On success return 1, else 0 with Python exception already set.
*/
int
get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retBuffer)
psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess,
PVOID *retBuffer)
{
static ULONG initialBufferSize = 0x4000;
NTSTATUS status;
@ -443,12 +381,12 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
PSYSTEM_PROCESS_INFORMATION process;
// get NtQuerySystemInformation
typedef DWORD (_stdcall *NTQSI_PROC) (int, PVOID, ULONG, PULONG);
typedef DWORD (_stdcall * NTQSI_PROC) (int, PVOID, ULONG, PULONG);
NTQSI_PROC NtQuerySystemInformation;
HINSTANCE hNtDll;
hNtDll = LoadLibrary(TEXT("ntdll.dll"));
NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress(
hNtDll, "NtQuerySystemInformation");
hNtDll, "NtQuerySystemInformation");
bufferSize = initialBufferSize;
buffer = malloc(bufferSize);
@ -461,7 +399,8 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
status = NtQuerySystemInformation(SystemProcessInformation, buffer,
bufferSize, &bufferSize);
if (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INFO_LENGTH_MISMATCH)
if (status == STATUS_BUFFER_TOO_SMALL ||
status == STATUS_INFO_LENGTH_MISMATCH)
{
free(buffer);
buffer = malloc(bufferSize);

View File

@ -2,22 +2,16 @@
* Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Helper functions related to fetching process information. Used by _psutil_mswindows
* module methods.
*/
#include <Python.h>
#include <windows.h>
DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
HANDLE psutil_handle_from_pid(DWORD pid);
HANDLE psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess);
HANDLE psutil_handle_from_pid(DWORD pid);
PVOID psutil_get_peb_address(HANDLE ProcessHandle);
HANDLE psutil_handle_from_pid(DWORD pid);
int psutil_handlep_is_running(HANDLE hProcess);
int psutil_pid_in_proclist(DWORD pid);
int psutil_pid_is_running(DWORD pid);
int psutil_handlep_is_running(HANDLE hProcess);
PVOID psutil_get_peb_address(HANDLE ProcessHandle);
PyObject* psutil_get_arg_list(long pid);
PyObject* psutil_get_ppid(long pid);
PyObject* psutil_get_name(long pid);
DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);

View File

@ -10,17 +10,17 @@
#include <windows.h>
#include <Python.h>
/*
* Convert a process handle to a process token handle.
*/
HANDLE
token_from_handle(HANDLE hProcess) {
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;
}
@ -38,16 +38,17 @@ token_from_handle(HANDLE hProcess) {
* string SeTcbPrivilege. If the function returns this string, then this
* account has Local System privileges
*/
int HasSystemPrivilege(HANDLE hProcess) {
int
psutil_has_system_privilege(HANDLE hProcess) {
DWORD i;
DWORD dwSize = 0;
DWORD dwRetval = 0;
TCHAR privName[256];
DWORD dwNameSize = 256;
//PTOKEN_PRIVILEGES tp = NULL;
// PTOKEN_PRIVILEGES tp = NULL;
BYTE *pBuffer = NULL;
TOKEN_PRIVILEGES* tp = NULL;
HANDLE hToken = token_from_handle(hProcess);
TOKEN_PRIVILEGES *tp = NULL;
HANDLE hToken = psutil_token_from_handle(hProcess);
if (NULL == hToken) {
return -1;
@ -64,32 +65,34 @@ int HasSystemPrivilege(HANDLE hProcess) {
}
// allocate buffer and call GetTokenInformation again
//tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize);
// tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize);
pBuffer = (BYTE *) malloc(dwSize);
if (pBuffer == NULL) {
PyErr_NoMemory();
return -1;
}
if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwSize, &dwSize) ) {
if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer,
dwSize, &dwSize))
{
PyErr_SetFromWindowsErr(0);
free(pBuffer);
return -1;
}
// convert the BYTE buffer to a TOKEN_PRIVILEGES struct pointer
tp = (TOKEN_PRIVILEGES*)pBuffer;
tp = (TOKEN_PRIVILEGES *)pBuffer;
// check all the privileges looking for SeTcbPrivilege
for(i=0; i < tp->PrivilegeCount; i++) {
for (i = 0; i < tp->PrivilegeCount; i++) {
// reset the buffer contents and the buffer size
strcpy(privName, "");
dwNameSize = sizeof(privName) / sizeof(TCHAR);
if (! LookupPrivilegeName(NULL,
&tp->Privileges[i].Luid,
(LPTSTR)privName,
&dwNameSize)) {
&tp->Privileges[i].Luid,
(LPTSTR)privName,
&dwNameSize))
{
PyErr_SetFromWindowsErr(0);
free(pBuffer);
return -1;
@ -100,22 +103,22 @@ int HasSystemPrivilege(HANDLE hProcess) {
free(pBuffer);
return 1;
}
} //for
}
free(pBuffer);
return 0;
}
BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege)
BOOL
psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
if(!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;
if (!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE;
// first pass. get current privilege setting
tp.PrivilegeCount = 1;
@ -137,13 +140,13 @@ BOOL SetPrivilege(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 {
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
tpPrevious.Privileges[0].Attributes ^=
(SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(
@ -161,16 +164,17 @@ BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege)
}
int SetSeDebug()
int
psutil_set_se_debug()
{
HANDLE hToken;
if(! OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
){
if (GetLastError() == ERROR_NO_TOKEN){
if (!ImpersonateSelf(SecurityImpersonation)){
if (! OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
) {
if (GetLastError() == ERROR_NO_TOKEN) {
if (!ImpersonateSelf(SecurityImpersonation)) {
CloseHandle(hToken);
return 0;
}
@ -178,7 +182,7 @@ int SetSeDebug()
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
){
) {
RevertToSelf();
CloseHandle(hToken);
return 0;
@ -187,7 +191,7 @@ int SetSeDebug()
}
// enable SeDebugPrivilege (open any process)
if (! SetPrivilege(hToken, SE_DEBUG_NAME, TRUE)){
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE)) {
RevertToSelf();
CloseHandle(hToken);
return 0;
@ -199,34 +203,33 @@ int SetSeDebug()
}
int UnsetSeDebug()
int
psutil_unset_se_debug()
{
HANDLE hToken;
if(! OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
){
if(GetLastError() == ERROR_NO_TOKEN){
if(! ImpersonateSelf(SecurityImpersonation)){
//Log2File("Error setting impersonation! [UnsetSeDebug()]", L_DEBUG);
if (! OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
) {
if (GetLastError() == ERROR_NO_TOKEN) {
if (! ImpersonateSelf(SecurityImpersonation)) {
return 0;
}
if(!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
){
//Log2File("Error Opening Thread Token! [UnsetSeDebug()]", L_DEBUG);
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
FALSE,
&hToken)
)
{
return 0;
}
}
}
//now disable SeDebug
if(!SetPrivilege(hToken, SE_DEBUG_NAME, FALSE)){
//Log2File("Error unsetting SeDebug Privilege [SetPrivilege()]", L_WARN);
// now disable SeDebug
if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) {
return 0;
}

View File

@ -9,10 +9,9 @@
#include <windows.h>
BOOL SetPrivilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege);
int SetSeDebug();
int UnsetSeDebug();
HANDLE token_from_handle(HANDLE hProcess);
int HasSystemPrivilege(HANDLE hProcess);
BOOL psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege);
HANDLE psutil_token_from_handle(HANDLE hProcess);
int psutil_has_system_privilege(HANDLE hProcess);
int psutil_set_se_debug();
int psutil_unset_se_debug();

View File

@ -1,19 +0,0 @@
#!/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.
"""This module is deprecated as exceptions are defined in _error.py
and are supposed to be accessed from 'psutil' namespace as in:
- psutil.NoSuchProcess
- psutil.AccessDenied
- psutil.TimeoutExpired
"""
import warnings
from psutil._error import *
warnings.warn("psutil.error module is deprecated and scheduled for removal; " \
"use psutil namespace instead", category=DeprecationWarning,
stacklevel=2)

View File

@ -4,41 +4,24 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import sys
"""psutil is a cross-platform library for retrieving information on
running processes and system utilization (CPU, memory, disks, network)
in Python.
"""
import os
import shutil
import fnmatch
import sys
try:
from setuptools import setup, Extension
except ImportError:
from distutils.core import setup, Extension
def clean():
"""'python setup.py clean' custom command."""
def rglob(path, pattern):
return [os.path.join(dirpath, f)
for dirpath, dirnames, files in os.walk(path)
for f in fnmatch.filter(files, pattern)]
HERE = os.path.abspath(os.path.dirname(__file__))
for dirname in ('build', 'dist'):
if os.path.isdir(dirname):
sys.stdout.write('removing directory: %s\n' % dirname)
shutil.rmtree(dirname)
for dirpath, dirnames, files in os.walk('.'):
if dirpath.endswith(('__pycache__', '.egg-info')):
sys.stdout.write('removing directory %s\n' % dirpath)
shutil.rmtree(dirpath)
for pattern in ['*.py[co]', '*.s[ol]', '*~', '*.orig', '*.rej', '*.swp']:
for x in rglob('.', pattern):
sys.stdout.write('removing file %s\n' % x)
os.remove(x)
def get_version():
INIT = os.path.abspath(os.path.join(os.path.dirname(__file__),
'psutil', '__init__.py'))
INIT = os.path.join(HERE, 'psutil/__init__.py')
f = open(INIT, 'r')
try:
for line in f:
@ -53,21 +36,22 @@ def get_version():
finally:
f.close()
def get_description():
README = os.path.abspath(os.path.join(os.path.dirname(__file__), 'README'))
README = os.path.join(HERE, 'README.rst')
f = open(README, 'r')
try:
return f.read()
finally:
f.close()
VERSION = get_version()
# POSIX
if os.name == 'posix':
posix_extension = Extension('_psutil_posix',
sources = ['psutil/_psutil_posix.c'])
posix_extension = Extension(
'_psutil_posix',
sources=['psutil/_psutil_posix.c'],
)
# Windows
if sys.platform.startswith("win32"):
@ -75,119 +59,137 @@ if sys.platform.startswith("win32"):
maj, min = sys.getwindowsversion()[0:2]
return '0x0%s' % ((maj * 100) + min)
extensions = [Extension('_psutil_mswindows',
sources=['psutil/_psutil_mswindows.c',
'psutil/_psutil_common.c',
'psutil/arch/mswindows/process_info.c',
'psutil/arch/mswindows/process_handles.c',
'psutil/arch/mswindows/security.c'],
define_macros=[('_WIN32_WINNT', get_winver()),
('_AVAIL_WINVER_', get_winver())],
libraries=["psapi", "kernel32", "advapi32",
"shell32", "netapi32", "iphlpapi",
"wtsapi32"],
#extra_compile_args=["/Z7"],
#extra_link_args=["/DEBUG"]
)]
extensions = [Extension(
'_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',
],
define_macros=[
# be nice to mingw, see:
# http://www.mingw.org/wiki/Use_more_recent_defined_functions
('_WIN32_WINNT', get_winver()),
('_AVAIL_WINVER_', get_winver()),
# see: https://github.com/giampaolo/psutil/issues/348
('PSAPI_VERSION', 1),
],
libraries=[
"psapi", "kernel32", "advapi32", "shell32", "netapi32", "iphlpapi",
"wtsapi32",
],
# extra_compile_args=["/Z7"],
# extra_link_args=["/DEBUG"]
)]
# OS X
elif sys.platform.startswith("darwin"):
extensions = [Extension('_psutil_osx',
sources = ['psutil/_psutil_osx.c',
'psutil/_psutil_common.c',
'psutil/arch/osx/process_info.c'],
extra_link_args=['-framework', 'CoreFoundation',
'-framework', 'IOKit']
),
posix_extension]
extensions = [Extension(
'_psutil_osx',
sources=[
'psutil/_psutil_osx.c',
'psutil/_psutil_common.c',
'psutil/arch/osx/process_info.c'
],
extra_link_args=[
'-framework', 'CoreFoundation', '-framework', 'IOKit'
],
),
posix_extension,
]
# FreeBSD
elif sys.platform.startswith("freebsd"):
extensions = [Extension('_psutil_bsd',
sources = ['psutil/_psutil_bsd.c',
'psutil/_psutil_common.c',
'psutil/arch/bsd/process_info.c'],
libraries=["devstat"],
),
posix_extension]
extensions = [Extension(
'_psutil_bsd',
sources=[
'psutil/_psutil_bsd.c',
'psutil/_psutil_common.c',
'psutil/arch/bsd/process_info.c'
],
libraries=["devstat"]),
posix_extension,
]
# Linux
elif sys.platform.startswith("linux"):
extensions = [Extension('_psutil_linux',
sources=['psutil/_psutil_linux.c'],
),
posix_extension]
extensions = [Extension(
'_psutil_linux',
sources=['psutil/_psutil_linux.c']),
posix_extension,
]
# Solaris
elif sys.platform.lower().startswith('sunos'):
extensions = [Extension('_psutil_sunos',
sources=['psutil/_psutil_sunos.c'],
libraries=['kstat', 'nsl'],
),
posix_extension]
extensions = [Extension(
'_psutil_sunos',
sources=['psutil/_psutil_sunos.c'],
libraries=['kstat', 'nsl'],),
posix_extension,
]
else:
sys.exit('platform %s is not supported' % sys.platform)
def main():
# "python setup.py clean" custom command
if len(sys.argv) > 1 and sys.argv[1] == 'clean':
return clean()
setup_args = dict(
name='psutil',
version=VERSION,
download_url="http://psutil.googlecode.com/files/psutil-%s.tar.gz" \
% VERSION,
description='A process and system utilities module for Python',
version=get_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',],
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',
],
author='Giampaolo Rodola',
author_email='psutil@googlegroups.com',
maintainer='Giampaolo Rodola',
maintainer_email='g.rodola <at> gmail <dot> com',
url='http://code.google.com/p/psutil/',
author_email='g.rodola <at> gmail <dot> com',
url='https://github.com/giampaolo/psutil',
platforms='Platform Independent',
license='License :: OSI Approved :: BSD License',
license='BSD',
packages=['psutil'],
test_suite='test.test_psutil',
# see: python setup.py register --list-classifiers
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft',
'Operating System :: Microsoft :: Windows :: Windows NT/2000',
'Operating System :: POSIX',
'Operating System :: POSIX :: Linux',
'Operating System :: POSIX :: BSD :: FreeBSD',
'Operating System :: POSIX :: SunOS/Solaris',
'Operating System :: OS Independent',
'Programming Language :: C',
'Programming Language :: Python',
'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',
'Programming Language :: Python :: 3.0',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Topic :: System :: Monitoring',
'Topic :: System :: Networking',
'Topic :: System :: Networking :: Monitoring',
'Topic :: System :: Benchmark',
'Topic :: System :: Hardware',
'Topic :: System :: Systems Administration',
'Topic :: Utilities',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Intended Audience :: Developers',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: BSD License',
],
)
'Development Status :: 5 - Production/Stable',
'Environment :: Console',
'Environment :: Win32 (MS Windows)',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: BSD License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows :: Windows NT/2000',
'Operating System :: Microsoft',
'Operating System :: OS Independent',
'Operating System :: POSIX :: BSD :: FreeBSD',
'Operating System :: POSIX :: Linux',
'Operating System :: POSIX :: SunOS/Solaris',
'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',
'Programming Language :: Python :: 3.0',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Programming Language :: Python',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Libraries',
'Topic :: System :: Benchmark',
'Topic :: System :: Hardware',
'Topic :: System :: Monitoring',
'Topic :: System :: Networking :: Monitoring',
'Topic :: System :: Networking',
'Topic :: System :: Systems Administration',
'Topic :: Utilities',
],
)
if extensions is not None:
setup_args["ext_modules"] = extensions
setup(**setup_args)

15
python/psutil/test/README Normal file
View File

@ -0,0 +1,15 @@
- 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

@ -4,23 +4,27 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# TODO: add test for comparing connections with 'sockstat' cmd
"""BSD specific tests. These are implicitly run by test_psutil.py."""
import unittest
import subprocess
import time
import re
import sys
import os
import psutil
from psutil._compat import PY3
from test_psutil import *
from test_psutil import (TOLERANCE, sh, get_test_subprocess, which,
retry_before_failing, reap_children, unittest)
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
MUSE_AVAILABLE = which('muse')
if os.getuid() == 0: # muse requires root privileges
MUSE_AVAILABLE = which('muse')
else:
MUSE_AVAILABLE = False
def sysctl(cmdline):
@ -34,9 +38,10 @@ def sysctl(cmdline):
except ValueError:
return result
def muse(field):
"""Thin wrapper around 'muse' cmdline utility."""
out = sh('muse', stderr=DEVNULL)
out = sh('muse')
for line in out.split('\n'):
if line.startswith(field):
break
@ -47,27 +52,29 @@ def muse(field):
class BSDSpecificTestCase(unittest.TestCase):
def setUp(self):
self.pid = get_test_subprocess().pid
@classmethod
def setUpClass(cls):
cls.pid = get_test_subprocess().pid
def tearDown(self):
@classmethod
def tearDownClass(cls):
reap_children()
def test_BOOT_TIME(self):
def test_boot_time(self):
s = sysctl('sysctl kern.boottime')
s = s[s.find(" sec = ") + 7:]
s = s[:s.find(',')]
btime = int(s)
self.assertEqual(btime, psutil.BOOT_TIME)
self.assertEqual(btime, psutil.boot_time())
def test_process_create_time(self):
cmdline = "ps -o lstart -p %s" %self.pid
cmdline = "ps -o lstart -p %s" % self.pid
p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
output = p.communicate()[0]
if PY3:
output = str(output, sys.stdout.encoding)
start_ps = output.replace('STARTED', '').strip()
start_psutil = psutil.Process(self.pid).create_time
start_psutil = psutil.Process(self.pid).create_time()
start_psutil = time.strftime("%a %b %e %H:%M:%S %Y",
time.localtime(start_psutil))
self.assertEqual(start_ps, start_psutil)
@ -101,7 +108,7 @@ class BSDSpecificTestCase(unittest.TestCase):
def test_memory_maps(self):
out = sh('procstat -v %s' % self.pid)
maps = psutil.Process(self.pid).get_memory_maps(grouped=False)
maps = psutil.Process(self.pid).memory_maps(grouped=False)
lines = out.split('\n')[1:]
while lines:
line = lines.pop()

View File

@ -7,22 +7,23 @@
"""Linux specific tests. These are implicitly run by test_psutil.py."""
from __future__ import division
import unittest
import subprocess
import sys
import time
import os
import re
import sys
import time
from test_psutil import POSIX, TOLERANCE, TRAVIS
from test_psutil import (skip_on_not_implemented, sh, get_test_subprocess,
retry_before_failing, get_kernel_version, unittest)
from test_psutil import *
from psutil._compat import PY3
import psutil
class LinuxSpecificTestCase(unittest.TestCase):
@unittest.skipIf(POSIX and not hasattr(os, 'statvfs'),
reason="os.statvfs() function not available on this platform")
@unittest.skipIf(
POSIX and not hasattr(os, 'statvfs'),
reason="os.statvfs() function not available on this platform")
@skip_on_not_implemented()
def test_disks(self):
# test psutil.disk_usage() and psutil.disk_partitions()
@ -53,9 +54,11 @@ class LinuxSpecificTestCase(unittest.TestCase):
sproc = get_test_subprocess()
time.sleep(1)
p = psutil.Process(sproc.pid)
maps = p.get_memory_maps(grouped=False)
maps = p.memory_maps(grouped=False)
pmap = sh('pmap -x %s' % p.pid).split('\n')
del pmap[0]; del pmap[0] # get rid of header
# get rid of header
del pmap[0]
del pmap[0]
while maps and pmap:
this = maps.pop(0)
other = pmap.pop(0)
@ -118,13 +121,11 @@ class LinuxSpecificTestCase(unittest.TestCase):
self.assertAlmostEqual(free, psutil.swap_memory().free,
delta=TOLERANCE)
@unittest.skipIf(TRAVIS, "unknown failure on travis")
def test_cpu_times(self):
fields = psutil.cpu_times()._fields
kernel_ver = re.findall('\d.\d.\d', os.uname()[2])[0]
kernel_ver = re.findall('\d+\.\d+\.\d+', os.uname()[2])[0]
kernel_ver_info = tuple(map(int, kernel_ver.split('.')))
# steal >= 2.6.11
# guest >= 2.6.24
# guest_nice >= 3.2.0
if kernel_ver_info >= (2, 6, 11):
self.assertIn('steal', fields)
else:
@ -138,6 +139,41 @@ class LinuxSpecificTestCase(unittest.TestCase):
else:
self.assertNotIn('guest_nice', fields)
# --- tests for specific kernel versions
@unittest.skipUnless(
get_kernel_version() >= (2, 6, 36),
"prlimit() not available on this Linux kernel version")
def test_prlimit_availability(self):
# prlimit() should be available starting from kernel 2.6.36
p = psutil.Process(os.getpid())
p.rlimit(psutil.RLIMIT_NOFILE)
# if prlimit() is supported *at least* these constants should
# be available
self.assertTrue(hasattr(psutil, "RLIM_INFINITY"))
self.assertTrue(hasattr(psutil, "RLIMIT_AS"))
self.assertTrue(hasattr(psutil, "RLIMIT_CORE"))
self.assertTrue(hasattr(psutil, "RLIMIT_CPU"))
self.assertTrue(hasattr(psutil, "RLIMIT_DATA"))
self.assertTrue(hasattr(psutil, "RLIMIT_FSIZE"))
self.assertTrue(hasattr(psutil, "RLIMIT_LOCKS"))
self.assertTrue(hasattr(psutil, "RLIMIT_MEMLOCK"))
self.assertTrue(hasattr(psutil, "RLIMIT_NOFILE"))
self.assertTrue(hasattr(psutil, "RLIMIT_NPROC"))
self.assertTrue(hasattr(psutil, "RLIMIT_RSS"))
self.assertTrue(hasattr(psutil, "RLIMIT_STACK"))
@unittest.skipUnless(
get_kernel_version() >= (3, 0),
"prlimit constants not available on this Linux kernel version")
def test_resource_consts_kernel_v(self):
# more recent constants
self.assertTrue(hasattr(psutil, "RLIMIT_MSGQUEUE"))
self.assertTrue(hasattr(psutil, "RLIMIT_NICE"))
self.assertTrue(hasattr(psutil, "RLIMIT_RTPRIO"))
self.assertTrue(hasattr(psutil, "RLIMIT_RTTIME"))
self.assertTrue(hasattr(psutil, "RLIMIT_SIGPENDING"))
def test_main():
test_suite = unittest.TestSuite()

View File

@ -6,17 +6,17 @@
"""OSX specific tests. These are implicitly run by test_psutil.py."""
import unittest
import subprocess
import time
import sys
import os
import re
import subprocess
import sys
import time
import psutil
from psutil._compat import PY3
from test_psutil import *
from test_psutil import (TOLERANCE, sh, get_test_subprocess, reap_children,
retry_before_failing, unittest)
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
@ -35,6 +35,7 @@ def sysctl(cmdline):
except ValueError:
return result
def vm_stat(field):
"""Wrapper around 'vm_stat' cmdline utility."""
out = sh('vm_stat')
@ -48,20 +49,22 @@ def vm_stat(field):
class OSXSpecificTestCase(unittest.TestCase):
def setUp(self):
self.pid = get_test_subprocess().pid
@classmethod
def setUpClass(cls):
cls.pid = get_test_subprocess().pid
def tearDown(self):
@classmethod
def tearDownClass(cls):
reap_children()
def test_process_create_time(self):
cmdline = "ps -o lstart -p %s" %self.pid
cmdline = "ps -o lstart -p %s" % self.pid
p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
output = p.communicate()[0]
if PY3:
output = str(output, sys.stdout.encoding)
start_ps = output.replace('STARTED', '').strip()
start_psutil = psutil.Process(self.pid).create_time
start_psutil = psutil.Process(self.pid).create_time()
start_psutil = time.strftime("%a %b %e %H:%M:%S %Y",
time.localtime(start_psutil))
self.assertEqual(start_ps, start_psutil)
@ -97,7 +100,7 @@ class OSXSpecificTestCase(unittest.TestCase):
def test_vmem_total(self):
sysctl_hwphymem = sysctl('sysctl hw.memsize')
self.assertEqual(sysctl_hwphymem, psutil.TOTAL_PHYMEM)
self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total)
@retry_before_failing()
def test_vmem_free(self):

116
python/psutil/test/_posix.py Executable file → Normal file
View File

@ -6,17 +6,19 @@
"""POSIX specific tests. These are implicitly run by test_psutil.py."""
import unittest
import subprocess
import time
import sys
import os
import datetime
import os
import subprocess
import sys
import time
import psutil
from psutil._compat import PY3
from test_psutil import *
from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON
from test_psutil import (get_test_subprocess, skip_on_access_denied,
retry_before_failing, reap_children, sh, unittest,
get_kernel_version, wait_for_pid)
def ps(cmd):
@ -43,75 +45,82 @@ def ps(cmd):
class PosixSpecificTestCase(unittest.TestCase):
"""Compare psutil results against 'ps' command line utility."""
# for ps -o arguments see: http://unixhelp.ed.ac.uk/CGI/man-cgi?ps
@classmethod
def setUpClass(cls):
cls.pid = get_test_subprocess([PYTHON, "-E", "-O"],
stdin=subprocess.PIPE).pid
wait_for_pid(cls.pid)
def setUp(self):
self.pid = get_test_subprocess([PYTHON, "-E", "-O"],
stdin=subprocess.PIPE).pid
def tearDown(self):
@classmethod
def tearDownClass(cls):
reap_children()
# for ps -o arguments see: http://unixhelp.ed.ac.uk/CGI/man-cgi?ps
def test_process_parent_pid(self):
ppid_ps = ps("ps --no-headers -o ppid -p %s" %self.pid)
ppid_psutil = psutil.Process(self.pid).ppid
ppid_ps = ps("ps --no-headers -o ppid -p %s" % self.pid)
ppid_psutil = psutil.Process(self.pid).ppid()
self.assertEqual(ppid_ps, ppid_psutil)
def test_process_uid(self):
uid_ps = ps("ps --no-headers -o uid -p %s" %self.pid)
uid_psutil = psutil.Process(self.pid).uids.real
uid_ps = ps("ps --no-headers -o uid -p %s" % self.pid)
uid_psutil = psutil.Process(self.pid).uids().real
self.assertEqual(uid_ps, uid_psutil)
def test_process_gid(self):
gid_ps = ps("ps --no-headers -o rgid -p %s" %self.pid)
gid_psutil = psutil.Process(self.pid).gids.real
gid_ps = ps("ps --no-headers -o rgid -p %s" % self.pid)
gid_psutil = psutil.Process(self.pid).gids().real
self.assertEqual(gid_ps, gid_psutil)
def test_process_username(self):
username_ps = ps("ps --no-headers -o user -p %s" %self.pid)
username_psutil = psutil.Process(self.pid).username
username_ps = ps("ps --no-headers -o user -p %s" % self.pid)
username_psutil = psutil.Process(self.pid).username()
self.assertEqual(username_ps, username_psutil)
@skip_on_access_denied()
@retry_before_failing()
def test_process_rss_memory(self):
# give python interpreter some time to properly initialize
# so that the results are the same
time.sleep(0.1)
rss_ps = ps("ps --no-headers -o rss -p %s" %self.pid)
rss_psutil = psutil.Process(self.pid).get_memory_info()[0] / 1024
rss_ps = ps("ps --no-headers -o rss -p %s" % self.pid)
rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024
self.assertEqual(rss_ps, rss_psutil)
@skip_on_access_denied()
@retry_before_failing()
def test_process_vsz_memory(self):
# give python interpreter some time to properly initialize
# so that the results are the same
time.sleep(0.1)
vsz_ps = ps("ps --no-headers -o vsz -p %s" %self.pid)
vsz_psutil = psutil.Process(self.pid).get_memory_info()[1] / 1024
vsz_ps = ps("ps --no-headers -o vsz -p %s" % self.pid)
vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024
self.assertEqual(vsz_ps, vsz_psutil)
def test_process_name(self):
# use command + arg since "comm" keyword not supported on all platforms
name_ps = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0]
name_ps = ps("ps --no-headers -o command -p %s" % (
self.pid)).split(' ')[0]
# remove path if there is any, from the command
name_ps = os.path.basename(name_ps).lower()
name_psutil = psutil.Process(self.pid).name.lower()
name_psutil = psutil.Process(self.pid).name().lower()
self.assertEqual(name_ps, name_psutil)
@unittest.skipIf(OSX or BSD,
'ps -o start not available')
'ps -o start not available')
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
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")
time_psutil).strftime("%H:%M:%S")
self.assertEqual(time_ps, time_psutil_tstamp)
def test_process_exe(self):
ps_pathname = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0]
psutil_pathname = psutil.Process(self.pid).exe
ps_pathname = ps("ps --no-headers -o command -p %s" %
self.pid).split(' ')[0]
psutil_pathname = psutil.Process(self.pid).exe()
try:
self.assertEqual(ps_pathname, psutil_pathname)
except AssertionError:
@ -125,15 +134,15 @@ class PosixSpecificTestCase(unittest.TestCase):
self.assertEqual(ps_pathname, adjusted_ps_pathname)
def test_process_cmdline(self):
ps_cmdline = ps("ps --no-headers -o command -p %s" %self.pid)
psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline)
ps_cmdline = ps("ps --no-headers -o command -p %s" % self.pid)
psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline())
if SUNOS:
# ps on Solaris only shows the first part of the cmdline
psutil_cmdline = psutil_cmdline.split(" ")[0]
self.assertEqual(ps_cmdline, psutil_cmdline)
@retry_before_failing()
def test_get_pids(self):
def test_pids(self):
# Note: this test might fail if the OS is starting/killing
# other processes in the meantime
if SUNOS:
@ -151,7 +160,7 @@ class PosixSpecificTestCase(unittest.TestCase):
pids_ps.append(pid)
# remove ps subprocess pid which is supposed to be dead in meantime
pids_ps.remove(p.pid)
pids_psutil = psutil.get_pid_list()
pids_psutil = psutil.pids()
pids_ps.sort()
pids_psutil.sort()
@ -179,13 +188,14 @@ class PosixSpecificTestCase(unittest.TestCase):
else:
self.fail("couldn't find %s nic in 'ifconfig -a' output" % nic)
def test_get_users(self):
@retry_before_failing()
def test_users(self):
out = sh("who")
lines = out.split('\n')
users = [x.split()[0] for x in lines]
self.assertEqual(len(users), len(psutil.get_users()))
self.assertEqual(len(users), len(psutil.users()))
terminals = [x.split()[1] for x in lines]
for u in psutil.get_users():
for u in psutil.users():
self.assertTrue(u.name in users, u.name)
self.assertTrue(u.terminal in terminals, u.terminal)
@ -193,27 +203,35 @@ class PosixSpecificTestCase(unittest.TestCase):
# Note: this fails from time to time; I'm keen on thinking
# it doesn't mean something is broken
def call(p, attr):
args = ()
attr = getattr(p, name, None)
if attr is not None and callable(attr):
ret = attr()
if name == 'rlimit':
args = (psutil.RLIMIT_NOFILE,)
elif name == 'set_rlimit':
args = (psutil.RLIMIT_NOFILE, (5, 5))
attr(*args)
else:
ret = attr
attr
p = psutil.Process(os.getpid())
attrs = []
failures = []
ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice',
'send_signal', 'wait', 'children', 'as_dict']
if LINUX and get_kernel_version() < (2, 6, 36):
ignored_names.append('rlimit')
for name in dir(psutil.Process):
if name.startswith('_') \
or name.startswith('set_') \
or name in ('terminate', 'kill', 'suspend', 'resume', 'nice',
'send_signal', 'wait', 'get_children', 'as_dict'):
if (name.startswith('_')
or name.startswith('set_')
or name.startswith('get') # deprecated APIs
or name in ignored_names):
continue
else:
try:
num1 = p.get_num_fds()
num1 = p.num_fds()
for x in range(2):
call(p, name)
num2 = p.get_num_fds()
num2 = p.num_fds()
except psutil.AccessDenied:
pass
else:
@ -225,8 +243,6 @@ class PosixSpecificTestCase(unittest.TestCase):
self.fail('\n' + '\n'.join(failures))
def test_main():
test_suite = unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase))

View File

@ -6,8 +6,10 @@
"""Sun OS specific tests. These are implicitly run by test_psutil.py."""
import sys
from test_psutil import sh, unittest
import psutil
from test_psutil import *
class SunOSSpecificTestCase(unittest.TestCase):

View File

@ -6,44 +6,55 @@
"""Windows specific tests. These are implicitly run by test_psutil.py."""
import errno
import os
import unittest
import platform
import signal
import time
import sys
import subprocess
import errno
import sys
import time
import traceback
import psutil
import _psutil_mswindows
from psutil._compat import PY3, callable, long
from test_psutil import *
from test_psutil import (get_test_subprocess, reap_children, unittest)
try:
import wmi
except ImportError:
err = sys.exc_info()[1]
register_warning("Couldn't run wmi tests: %s" % str(err))
wmi = None
try:
import win32api
import win32con
except ImportError:
err = sys.exc_info()[1]
register_warning("Couldn't run pywin32 tests: %s" % str(err))
win32api = None
win32api = win32con = None
from psutil._compat import PY3, callable, long
from psutil._pswindows import ACCESS_DENIED_SET
import _psutil_windows
import psutil
def wrap_exceptions(fun):
def wrapper(self, *args, **kwargs):
try:
return fun(self, *args, **kwargs)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise psutil.AccessDenied(None, None)
if err.errno == errno.ESRCH:
raise psutil.NoSuchProcess(None, None)
raise
return wrapper
class WindowsSpecificTestCase(unittest.TestCase):
def setUp(self):
sproc = get_test_subprocess()
wait_for_pid(sproc.pid)
self.pid = sproc.pid
@classmethod
def setUpClass(cls):
cls.pid = get_test_subprocess().pid
def tearDown(self):
@classmethod
def tearDownClass(cls):
reap_children()
def test_issue_24(self):
@ -52,14 +63,14 @@ class WindowsSpecificTestCase(unittest.TestCase):
def test_special_pid(self):
p = psutil.Process(4)
self.assertEqual(p.name, 'System')
self.assertEqual(p.name(), 'System')
# use __str__ to access all common Process properties to check
# that nothing strange happens
str(p)
p.username
self.assertTrue(p.create_time >= 0.0)
p.username()
self.assertTrue(p.create_time() >= 0.0)
try:
rss, vms = p.get_memory_info()
rss, vms = p.memory_info()
except psutil.AccessDenied:
# expected on Windows Vista and Windows 7
if not platform.uname()[1] in ('vista', 'win-7', 'win7'):
@ -67,7 +78,7 @@ class WindowsSpecificTestCase(unittest.TestCase):
else:
self.assertTrue(rss > 0)
def test_signal(self):
def test_send_signal(self):
p = psutil.Process(self.pid)
self.assertRaises(ValueError, p.send_signal, signal.SIGINT)
@ -81,206 +92,205 @@ class WindowsSpecificTestCase(unittest.TestCase):
if "pseudo-interface" in nic.replace(' ', '-').lower():
continue
if nic not in out:
self.fail("%r nic wasn't found in 'ipconfig /all' output" % nic)
self.fail(
"%r nic wasn't found in 'ipconfig /all' output" % nic)
def test_exe(self):
for p in psutil.process_iter():
try:
self.assertEqual(os.path.basename(p.exe), p.name)
self.assertEqual(os.path.basename(p.exe()), p.name())
except psutil.Error:
pass
if wmi is not None:
# --- Process class tests
# --- Process class tests
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_name(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
self.assertEqual(p.name(), w.Caption)
def test_process_name(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
self.assertEqual(p.name, w.Caption)
@unittest.skipIf(wmi is None, "wmi module is not installed")
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)
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)
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_cmdline(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
self.assertEqual(' '.join(p.cmdline()),
w.CommandLine.replace('"', ''))
def test_process_cmdline(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
self.assertEqual(' '.join(p.cmdline), w.CommandLine.replace('"', ''))
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_username(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
domain, _, username = w.GetOwner()
username = "%s\\%s" % (domain, username)
self.assertEqual(p.username(), username)
def test_process_username(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
domain, _, username = w.GetOwner()
username = "%s\\%s" %(domain, username)
self.assertEqual(p.username, username)
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_rss_memory(self):
time.sleep(0.1)
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
rss = p.memory_info().rss
self.assertEqual(rss, int(w.WorkingSetSize))
def test_process_rss_memory(self):
time.sleep(0.1)
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
rss = p.get_memory_info().rss
self.assertEqual(rss, int(w.WorkingSetSize))
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_vms_memory(self):
time.sleep(0.1)
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
vms = p.memory_info().vms
# http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx
# ...claims that PageFileUsage is represented in Kilo
# bytes but funnily enough on certain platforms bytes are
# returned instead.
wmi_usage = int(w.PageFileUsage)
if (vms != wmi_usage) and (vms != wmi_usage * 1024):
self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms))
def test_process_vms_memory(self):
time.sleep(0.1)
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
vms = p.get_memory_info().vms
# http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx
# ...claims that PageFileUsage is represented in Kilo
# bytes but funnily enough on certain platforms bytes are
# returned instead.
wmi_usage = int(w.PageFileUsage)
if (vms != wmi_usage) and (vms != wmi_usage * 1024):
self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms))
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_process_create_time(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
wmic_create = str(w.CreationDate.split('.')[0])
psutil_create = time.strftime("%Y%m%d%H%M%S",
time.localtime(p.create_time()))
self.assertEqual(wmic_create, psutil_create)
def test_process_create_time(self):
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(self.pid)
wmic_create = str(w.CreationDate.split('.')[0])
psutil_create = time.strftime("%Y%m%d%H%M%S",
time.localtime(p.create_time))
self.assertEqual(wmic_create, psutil_create)
# --- psutil namespace functions and constants tests
@unittest.skipUnless(hasattr(os, 'NUMBER_OF_PROCESSORS'),
'NUMBER_OF_PROCESSORS env var is not available')
def test_cpu_count(self):
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
self.assertEqual(num_cpus, psutil.cpu_count())
# --- psutil namespace functions and constants tests
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_total_phymem(self):
w = wmi.WMI().Win32_ComputerSystem()[0]
self.assertEqual(int(w.TotalPhysicalMemory),
psutil.virtual_memory().total)
@unittest.skipUnless(hasattr(os, 'NUMBER_OF_PROCESSORS'),
'NUMBER_OF_PROCESSORS env var is not available')
def test_NUM_CPUS(self):
num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
self.assertEqual(num_cpus, psutil.NUM_CPUS)
# @unittest.skipIf(wmi is None, "wmi module is not installed")
# def test__UPTIME(self):
# # _UPTIME constant is not public but it is used internally
# # as value to return for pid 0 creation time.
# # WMI behaves the same.
# w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
# p = psutil.Process(0)
# wmic_create = str(w.CreationDate.split('.')[0])
# psutil_create = time.strftime("%Y%m%d%H%M%S",
# time.localtime(p.create_time()))
#
def test_TOTAL_PHYMEM(self):
w = wmi.WMI().Win32_ComputerSystem()[0]
self.assertEqual(int(w.TotalPhysicalMemory), psutil.TOTAL_PHYMEM)
@unittest.skipIf(wmi is None, "wmi module is not installed")
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))
def test__UPTIME(self):
# _UPTIME constant is not public but it is used internally
# as value to return for pid 0 creation time.
# WMI behaves the same.
w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
p = psutil.Process(0)
wmic_create = str(w.CreationDate.split('.')[0])
psutil_create = time.strftime("%Y%m%d%H%M%S",
time.localtime(p.create_time))
# XXX - ? no actual test here
def test_get_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.get_pid_list()
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))
def test_disks(self):
ps_parts = psutil.disk_partitions(all=True)
wmi_parts = wmi.WMI().Win32_LogicalDisk()
for ps_part in ps_parts:
for wmi_part in wmi_parts:
if ps_part.device.replace('\\', '') == wmi_part.DeviceID:
if not ps_part.mountpoint:
# this is usually a CD-ROM with no disk inserted
break
try:
usage = psutil.disk_usage(ps_part.mountpoint)
except OSError:
err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
# usually this is the floppy
break
else:
raise
self.assertEqual(usage.total, int(wmi_part.Size))
wmi_free = int(wmi_part.FreeSpace)
self.assertEqual(usage.free, wmi_free)
# 10 MB tollerance
if abs(usage.free - wmi_free) > 10 * 1024 * 1024:
self.fail("psutil=%s, wmi=%s" % usage.free, wmi_free)
@unittest.skipIf(wmi is None, "wmi module is not installed")
def test_disks(self):
ps_parts = psutil.disk_partitions(all=True)
wmi_parts = wmi.WMI().Win32_LogicalDisk()
for ps_part in ps_parts:
for wmi_part in wmi_parts:
if ps_part.device.replace('\\', '') == wmi_part.DeviceID:
if not ps_part.mountpoint:
# this is usually a CD-ROM with no disk inserted
break
else:
self.fail("can't find partition %s" % repr(ps_part))
if win32api is not None:
def test_get_num_handles(self):
p = psutil.Process(os.getpid())
before = p.get_num_handles()
handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION,
win32con.FALSE, os.getpid())
after = p.get_num_handles()
self.assertEqual(after, before+1)
win32api.CloseHandle(handle)
self.assertEqual(p.get_num_handles(), before)
def test_get_num_handles_2(self):
# Note: this fails from time to time; I'm keen on thinking
# it doesn't mean something is broken
def call(p, attr):
attr = getattr(p, name, None)
if attr is not None and callable(attr):
ret = attr()
else:
ret = attr
p = psutil.Process(self.pid)
attrs = []
failures = []
for name in dir(psutil.Process):
if name.startswith('_') \
or name.startswith('set_') \
or name in ('terminate', 'kill', 'suspend', 'resume', 'nice',
'send_signal', 'wait', 'get_children', 'as_dict'):
continue
else:
try:
call(p, name)
num1 = p.get_num_handles()
call(p, name)
num2 = p.get_num_handles()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
else:
if num2 > num1:
fail = "failure while processing Process.%s method " \
"(before=%s, after=%s)" % (name, num1, num2)
failures.append(fail)
if failures:
self.fail('\n' + '\n'.join(failures))
usage = psutil.disk_usage(ps_part.mountpoint)
except OSError:
err = sys.exc_info()[1]
if err.errno == errno.ENOENT:
# usually this is the floppy
break
else:
raise
self.assertEqual(usage.total, int(wmi_part.Size))
wmi_free = int(wmi_part.FreeSpace)
self.assertEqual(usage.free, wmi_free)
# 10 MB tollerance
if abs(usage.free - wmi_free) > 10 * 1024 * 1024:
self.fail("psutil=%s, wmi=%s" % (
usage.free, wmi_free))
break
else:
self.fail("can't find partition %s" % repr(ps_part))
@unittest.skipIf(win32api is None, "pywin32 module is not installed")
def test_num_handles(self):
p = psutil.Process(os.getpid())
before = p.num_handles()
handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION,
win32con.FALSE, os.getpid())
after = p.num_handles()
self.assertEqual(after, before + 1)
win32api.CloseHandle(handle)
self.assertEqual(p.num_handles(), before)
import _psutil_mswindows
from psutil._psmswindows import ACCESS_DENIED_SET
@unittest.skipIf(win32api is None, "pywin32 module is not installed")
def test_num_handles_2(self):
# Note: this fails from time to time; I'm keen on thinking
# it doesn't mean something is broken
def call(p, attr):
attr = getattr(p, name, None)
if attr is not None and callable(attr):
attr()
else:
attr
p = psutil.Process(self.pid)
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'):
continue
else:
try:
call(p, name)
num1 = p.num_handles()
call(p, name)
num2 = p.num_handles()
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
else:
if num2 > num1:
fail = \
"failure while processing Process.%s method " \
"(before=%s, after=%s)" % (name, num1, num2)
failures.append(fail)
if failures:
self.fail('\n' + '\n'.join(failures))
def wrap_exceptions(callable):
def wrapper(self, *args, **kwargs):
try:
return callable(self, *args, **kwargs)
except OSError:
err = sys.exc_info()[1]
if err.errno in ACCESS_DENIED_SET:
raise psutil.AccessDenied(None, None)
if err.errno == errno.ESRCH:
raise psutil.NoSuchProcess(None, None)
raise
return wrapper
class TestDualProcessImplementation(unittest.TestCase):
fun_names = [
# function name tolerance
('get_process_cpu_times', 0.2),
('get_process_create_time', 0.5),
('get_process_num_handles', 1), # 1 because impl #1 opens a handle
('get_process_io_counters', 0),
('get_process_memory_info', 1024), # KB
# 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
]
def test_compare_values(self):
@ -290,7 +300,7 @@ class TestDualProcessImplementation(unittest.TestCase):
# case the first fails because of limited permission error.
# Here we test that the two methods return the exact same value,
# see:
# http://code.google.com/p/psutil/issues/detail?id=304
# https://github.com/giampaolo/psutil/issues/304
def assert_ge_0(obj):
if isinstance(obj, tuple):
for value in obj:
@ -314,10 +324,10 @@ class TestDualProcessImplementation(unittest.TestCase):
failures = []
for name, tolerance in self.fun_names:
meth1 = wrap_exceptions(getattr(_psutil_mswindows, name))
meth2 = wrap_exceptions(getattr(_psutil_mswindows, name + '_2'))
meth1 = wrap_exceptions(getattr(_psutil_windows, name))
meth2 = wrap_exceptions(getattr(_psutil_windows, name + '_2'))
for p in psutil.process_iter():
if name == 'get_process_memory_info' and p.pid == os.getpid():
if name == 'proc_memory_info' and p.pid == os.getpid():
continue
#
try:
@ -343,10 +353,9 @@ class TestDualProcessImplementation(unittest.TestCase):
assert_ge_0(ret1)
assert_ge_0(ret2)
except AssertionError:
err = sys.exc_info()[1]
trace = traceback.format_exc()
msg = '%s\npid=%s, method=%r, ret_1=%r, ret_2=%r' \
% (trace, p.pid, name, ret1, ret2)
msg = '%s\npid=%s, method=%r, ret_1=%r, ret_2=%r' % (
trace, p.pid, name, ret1, ret2)
failures.append(msg)
break
if failures:
@ -355,9 +364,9 @@ class TestDualProcessImplementation(unittest.TestCase):
def test_zombies(self):
# test that NPS is raised by the 2nd implementation in case a
# process no longer exists
ZOMBIE_PID = max(psutil.get_pid_list()) + 5000
ZOMBIE_PID = max(psutil.pids()) + 5000
for name, _ in self.fun_names:
meth = wrap_exceptions(getattr(_psutil_mswindows, name))
meth = wrap_exceptions(getattr(_psutil_windows, name))
self.assertRaises(psutil.NoSuchProcess, meth, ZOMBIE_PID)

View File

@ -10,29 +10,39 @@ functions many times and compare process memory usage before and
after the calls. It might produce false positives.
"""
import os
import gc
import unittest
import time
import os
import socket
import threading
import types
import sys
import threading
import time
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 PY3, callable, xrange
from test_psutil import *
# disable cache for Process class properties
psutil._common.cached_property.enabled = False
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
SKIP_PYTHON_IMPL = True
def skip_if_linux():
return unittest.skipIf(LINUX and SKIP_PYTHON_IMPL,
"not worth being tested on LINUX (pure python)")
class Base(unittest.TestCase):
proc = psutil.Process(os.getpid())
def execute(self, function, *args, **kwargs):
@ -72,11 +82,11 @@ class Base(unittest.TestCase):
rss3 = self.get_mem()
difference = rss3 - rss2
if rss3 > rss2:
self.fail("rss2=%s, rss3=%s, difference=%s" \
self.fail("rss2=%s, rss3=%s, difference=%s"
% (rss2, rss3, difference))
def get_mem(self):
return psutil.Process(os.getpid()).get_memory_info()[0]
return psutil.Process(os.getpid()).memory_info()[0]
def call(self, *args, **kwargs):
raise NotImplementedError("must be implemented in subclass")
@ -85,20 +95,6 @@ class Base(unittest.TestCase):
class TestProcessObjectLeaks(Base):
"""Test leaks of Process class methods and properties"""
def __init__(self, *args, **kwargs):
Base.__init__(self, *args, **kwargs)
# skip tests which are not supported by Process API
supported_attrs = dir(psutil.Process)
for attr in [x for x in dir(self) if x.startswith('test')]:
if attr[5:] not in supported_attrs:
meth = getattr(self, attr)
name = meth.__func__.__name__.replace('test_', '')
@unittest.skipIf(True,
"%s not supported on this platform" % name)
def test_(self):
pass
setattr(self, attr, types.MethodType(test_, self))
def setUp(self):
gc.collect()
@ -113,107 +109,153 @@ class TestProcessObjectLeaks(Base):
except psutil.Error:
pass
@skip_if_linux()
def test_name(self):
self.execute('name')
@skip_if_linux()
def test_cmdline(self):
self.execute('cmdline')
@skip_if_linux()
def test_exe(self):
self.execute('exe')
@skip_if_linux()
def test_ppid(self):
self.execute('ppid')
@unittest.skipUnless(POSIX, "POSIX only")
@skip_if_linux()
def test_uids(self):
self.execute('uids')
@unittest.skipUnless(POSIX, "POSIX only")
@skip_if_linux()
def test_gids(self):
self.execute('gids')
@skip_if_linux()
def test_status(self):
self.execute('status')
def test_get_nice(self):
self.execute('get_nice')
def test_nice_get(self):
self.execute('nice')
def test_set_nice(self):
niceness = psutil.Process(os.getpid()).get_nice()
self.execute('set_nice', niceness)
def test_nice_set(self):
niceness = psutil.Process(os.getpid()).nice()
self.execute('nice', niceness)
def test_get_io_counters(self):
self.execute('get_io_counters')
@unittest.skipUnless(hasattr(psutil.Process, 'ionice'),
"Linux and Windows Vista only")
def test_ionice_get(self):
self.execute('ionice')
def test_get_ionice(self):
self.execute('get_ionice')
def test_set_ionice(self):
@unittest.skipUnless(hasattr(psutil.Process, 'ionice'),
"Linux and Windows Vista only")
def test_ionice_set(self):
if WINDOWS:
value = psutil.Process(os.getpid()).get_ionice()
self.execute('set_ionice', value)
value = psutil.Process(os.getpid()).ionice()
self.execute('ionice', value)
else:
self.execute('set_ionice', psutil.IOPRIO_CLASS_NONE)
self.execute('ionice', psutil.IOPRIO_CLASS_NONE)
@unittest.skipIf(OSX, "feature not supported on this platform")
@skip_if_linux()
def test_io_counters(self):
self.execute('io_counters')
def test_username(self):
self.execute('username')
@skip_if_linux()
def test_create_time(self):
self.execute('create_time')
def test_get_num_threads(self):
self.execute('get_num_threads')
@skip_if_linux()
def test_num_threads(self):
self.execute('num_threads')
def test_get_num_handles(self):
self.execute('get_num_handles')
@unittest.skipUnless(WINDOWS, "Windows only")
def test_num_handles(self):
self.execute('num_handles')
def test_get_num_fds(self):
self.execute('get_num_fds')
@unittest.skipUnless(POSIX, "POSIX only")
@skip_if_linux()
def test_num_fds(self):
self.execute('num_fds')
def test_get_threads(self):
self.execute('get_threads')
@skip_if_linux()
def test_threads(self):
self.execute('threads')
def test_get_cpu_times(self):
self.execute('get_cpu_times')
@skip_if_linux()
def test_cpu_times(self):
self.execute('cpu_times')
def test_get_memory_info(self):
self.execute('get_memory_info')
@skip_if_linux()
def test_memory_info(self):
self.execute('memory_info')
def test_get_ext_memory_info(self):
self.execute('get_ext_memory_info')
@skip_if_linux()
def test_memory_info_ex(self):
self.execute('memory_info_ex')
@unittest.skipUnless(POSIX, "POSIX only")
@skip_if_linux()
def test_terminal(self):
self.execute('terminal')
@unittest.skipIf(POSIX, "not worth being tested on POSIX (pure python)")
@unittest.skipIf(POSIX and SKIP_PYTHON_IMPL,
"not worth being tested on POSIX (pure python)")
def test_resume(self):
self.execute('resume')
def test_getcwd(self):
self.execute('getcwd')
@skip_if_linux()
def test_cwd(self):
self.execute('cwd')
def test_get_cpu_affinity(self):
self.execute('get_cpu_affinity')
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
def test_cpu_affinity_get(self):
self.execute('cpu_affinity')
def test_set_cpu_affinity(self):
affinity = psutil.Process(os.getpid()).get_cpu_affinity()
self.execute('set_cpu_affinity', affinity)
@unittest.skipUnless(WINDOWS or LINUX, "Windows or Linux only")
def test_cpu_affinity_set(self):
affinity = psutil.Process(os.getpid()).cpu_affinity()
self.execute('cpu_affinity', affinity)
def test_get_open_files(self):
@skip_if_linux()
def test_open_files(self):
safe_remove(TESTFN) # needed after UNIX socket test has run
f = open(TESTFN, 'w')
try:
self.execute('get_open_files')
self.execute('open_files')
finally:
f.close()
# OSX implementation is unbelievably slow
@unittest.skipIf(OSX, "OSX implementation is too slow")
def test_get_memory_maps(self):
self.execute('get_memory_maps')
@skip_if_linux()
def test_memory_maps(self):
self.execute('memory_maps')
# Linux implementation is pure python so since it's slow we skip it
@unittest.skipIf(LINUX, "not worth being tested on Linux (pure python)")
def test_get_connections(self):
@unittest.skipUnless(LINUX, "Linux only")
@unittest.skipUnless(LINUX and RLIMIT_SUPPORT,
"only available on Linux >= 2.6.36")
def test_rlimit_get(self):
self.execute('rlimit', psutil.RLIMIT_NOFILE)
@unittest.skipUnless(LINUX, "Linux only")
@unittest.skipUnless(LINUX and RLIMIT_SUPPORT,
"only available on Linux >= 2.6.36")
def test_rlimit_set(self):
limit = psutil.Process().rlimit(psutil.RLIMIT_NOFILE)
self.execute('rlimit', psutil.RLIMIT_NOFILE, limit)
@skip_if_linux()
# Windows implementation is based on a single system-wide function
@unittest.skipIf(WINDOWS, "tested later")
def test_connections(self):
def create_socket(family, type):
sock = socket.socket(family, type)
sock.bind(('', 0))
@ -240,7 +282,7 @@ class TestProcessObjectLeaks(Base):
if SUNOS:
kind = 'inet'
try:
self.execute('get_connections', kind=kind)
self.execute('connections', kind=kind)
finally:
for s in socks:
s.close()
@ -252,6 +294,7 @@ DEAD_PROC.kill()
DEAD_PROC.wait()
del p
class TestProcessObjectLeaksZombie(TestProcessObjectLeaks):
"""Same as above but looks for leaks occurring when dealing with
zombie processes raising NoSuchProcess exception.
@ -284,9 +327,24 @@ class TestModuleFunctionsLeaks(Base):
def call(self, function, *args, **kwargs):
obj = getattr(psutil, function)
if callable(obj):
retvalue = obj(*args, **kwargs)
obj(*args, **kwargs)
@unittest.skipIf(POSIX, "not worth being tested on POSIX (pure python)")
@skip_if_linux()
def test_cpu_count_logical(self):
psutil.cpu_count = psutil._psplatform.cpu_count_logical
self.execute('cpu_count')
@skip_if_linux()
def test_cpu_count_physical(self):
psutil.cpu_count = psutil._psplatform.cpu_count_physical
self.execute('cpu_count')
@skip_if_linux()
def test_boot_time(self):
self.execute('boot_time')
@unittest.skipIf(POSIX and SKIP_PYTHON_IMPL,
"not worth being tested on POSIX (pure python)")
def test_pid_exists(self):
self.execute('pid_exists', os.getpid())
@ -299,37 +357,48 @@ class TestModuleFunctionsLeaks(Base):
def test_swap_memory(self):
self.execute('swap_memory')
@skip_if_linux()
def test_cpu_times(self):
self.execute('cpu_times')
@skip_if_linux()
def test_per_cpu_times(self):
self.execute('cpu_times', percpu=True)
@unittest.skipIf(POSIX, "not worth being tested on POSIX (pure python)")
@unittest.skipIf(POSIX and SKIP_PYTHON_IMPL,
"not worth being tested on POSIX (pure python)")
def test_disk_usage(self):
self.execute('disk_usage', '.')
def test_disk_partitions(self):
self.execute('disk_partitions')
@skip_if_linux()
def test_net_io_counters(self):
self.execute('net_io_counters')
@unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'),
'/proc/diskstats not available on this Linux version')
@skip_if_linux()
def test_disk_io_counters(self):
self.execute('disk_io_counters')
# XXX - on Windows this produces a false positive
@unittest.skipIf(WINDOWS,
"XXX produces a false positive on Windows")
def test_get_users(self):
self.execute('get_users')
@unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows")
def test_users(self):
self.execute('users')
@unittest.skipIf(LINUX,
"not worth being tested on Linux (pure python)")
def test_net_connections(self):
self.execute('net_connections')
def test_main():
test_suite = unittest.TestSuite()
tests = [TestProcessObjectLeaksZombie,
TestProcessObjectLeaks,
TestModuleFunctionsLeaks,]
TestModuleFunctionsLeaks]
for test in tests:
test_suite.addTest(unittest.makeSuite(test))
result = unittest.TextTestRunner(verbosity=2).run(test_suite)

File diff suppressed because it is too large Load Diff

24
python/psutil/tox.ini Normal file
View File

@ -0,0 +1,24 @@
# Tox (http://tox.testrun.org/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions.
# To use it run "pip install tox" and then run "tox" from this
# directory.
[tox]
envlist = py26, py27, py32, py33, py34
[testenv]
deps =
pytest
flake8
setenv =
PYTHONPATH = {toxinidir}/test
commands =
py.test {posargs}
flake8 --exclude=build,.tox,.git
[testenv:py26]
deps =
flake8
pytest
unittest2