mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
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:
parent
fa97bf9388
commit
9ee889e5ba
@ -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
|
||||
|
@ -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
885
python/psutil/HISTORY.rst
Normal 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
144
python/psutil/INSTALL.rst
Normal 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
|
@ -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
90
python/psutil/Makefile
Normal 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"
|
@ -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
|
||||
|
@ -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
349
python/psutil/README.rst
Normal 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>`_
|
@ -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
177
python/psutil/docs/Makefile
Normal 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
15
python/psutil/docs/README
Normal 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.
|
57
python/psutil/docs/_static/copybutton.js
vendored
Normal file
57
python/psutil/docs/_static/copybutton.js
vendored
Normal 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">>>></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
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
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
161
python/psutil/docs/_static/sidebar.js
vendored
Normal 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>«</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();
|
||||
});
|
12
python/psutil/docs/_template/globaltoc.html
vendored
Normal file
12
python/psutil/docs/_template/globaltoc.html
vendored
Normal 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>
|
4
python/psutil/docs/_template/indexcontent.html
vendored
Normal file
4
python/psutil/docs/_template/indexcontent.html
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{% extends "defindex.html" %}
|
||||
{% block tables %}
|
||||
|
||||
{% endblock %}
|
8
python/psutil/docs/_template/indexsidebar.html
vendored
Normal file
8
python/psutil/docs/_template/indexsidebar.html
vendored
Normal 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
66
python/psutil/docs/_template/page.html
vendored
Normal 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">
|
||||
© 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 %}
|
187
python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
vendored
Normal file
187
python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css
vendored
Normal 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;
|
||||
}
|
23
python/psutil/docs/_themes/pydoctheme/theme.conf
vendored
Normal file
23
python/psutil/docs/_themes/pydoctheme/theme.conf
vendored
Normal 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
262
python/psutil/docs/conf.py
Normal 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
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
242
python/psutil/docs/make.bat
Normal 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
|
@ -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())
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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())
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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', '', ''))
|
||||
|
||||
|
@ -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:
|
||||
|
81
python/psutil/examples/ps.py
Normal file
81
python/psutil/examples/ps.py
Normal 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()
|
@ -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),
|
||||
|
@ -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
230
python/psutil/make.bat
Normal 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
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
@ -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))
|
@ -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)
|
||||
|
@ -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():
|
||||
|
@ -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
@ -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
|
@ -22,6 +22,7 @@ NoSuchProcess(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set OSError(errno=EACCES, strerror="Permission denied") Python exception.
|
||||
*/
|
||||
|
@ -6,6 +6,5 @@
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
PyObject* NoSuchProcess(void);
|
||||
PyObject* AccessDenied(void);
|
||||
|
||||
PyObject* NoSuchProcess(void);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
70
python/psutil/psutil/_psutil_windows.h
Normal file
70
python/psutil/psutil/_psutil_windows.h
Normal 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);
|
490
python/psutil/psutil/_pswindows.py
Normal file
490
python/psutil/psutil/_pswindows.py
Normal 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)
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
41
python/psutil/psutil/arch/windows/glpi.h
Normal file
41
python/psutil/psutil/arch/windows/glpi.h
Normal 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);
|
@ -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,
|
@ -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",
|
@ -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.
|
@ -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);
|
@ -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);
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)
|
@ -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
15
python/psutil/test/README
Normal 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
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -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
116
python/psutil/test/_posix.py
Executable file → Normal 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))
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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
24
python/psutil/tox.ini
Normal 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
|
Loading…
Reference in New Issue
Block a user