OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # $Id: _psmswindows.py 802 2010-11-12 22:15:29Z g.rodola $ | 3 # $Id: _psmswindows.py 1142 2011-10-05 18:45:49Z g.rodola $ |
4 # | 4 # |
| 5 # Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. |
| 6 # Use of this source code is governed by a BSD-style license that can be |
| 7 # found in the LICENSE file. |
| 8 |
| 9 """Windows platform implementation.""" |
5 | 10 |
6 import errno | 11 import errno |
7 import os | 12 import os |
8 import subprocess | |
9 import socket | |
10 import re | |
11 import sys | 13 import sys |
12 import platform | 14 import platform |
13 | 15 |
14 try: | 16 import _psutil_mswindows |
15 from collections import namedtuple | 17 from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired |
16 except ImportError: | 18 from psutil._compat import namedtuple |
17 from psutil.compat import namedtuple # python < 2.6 | 19 from psutil._common import * |
18 | 20 |
19 import _psutil_mswindows | 21 # Windows specific extended namespace |
20 from psutil.error import AccessDenied, NoSuchProcess | 22 __extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", |
21 | 23 "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", |
| 24 "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS"] |
22 | 25 |
23 | 26 |
24 # --- module level constants (gets pushed up to psutil module) | 27 # --- module level constants (gets pushed up to psutil module) |
25 | 28 |
26 NUM_CPUS = _psutil_mswindows.get_num_cpus() | 29 NUM_CPUS = _psutil_mswindows.get_num_cpus() |
27 TOTAL_PHYMEM = _psutil_mswindows.get_total_phymem() | 30 BOOT_TIME = _psutil_mswindows.get_system_uptime() |
28 _UPTIME = _psutil_mswindows.get_system_uptime() | |
29 _WIN2000 = platform.win32_ver()[0] == '2000' | 31 _WIN2000 = platform.win32_ver()[0] == '2000' |
| 32 ERROR_ACCESS_DENIED = 5 |
| 33 WAIT_TIMEOUT = 0x00000102 # 258 in decimal |
30 | 34 |
31 ERROR_ACCESS_DENIED = 5 | 35 # process priority constants: |
| 36 # http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx |
| 37 from _psutil_mswindows import (ABOVE_NORMAL_PRIORITY_CLASS, |
| 38 BELOW_NORMAL_PRIORITY_CLASS, |
| 39 HIGH_PRIORITY_CLASS, |
| 40 IDLE_PRIORITY_CLASS, |
| 41 NORMAL_PRIORITY_CLASS, |
| 42 REALTIME_PRIORITY_CLASS, |
| 43 INFINITE) |
32 | 44 |
33 # --- public functions | 45 # --- public functions |
34 | 46 |
35 def avail_phymem(): | 47 def phymem_usage(): |
36 "Return the amount of physical memory available on the system, in bytes." | 48 """Physical system memory as a (total, used, free) tuple.""" |
37 return _psutil_mswindows.get_avail_phymem() | 49 all = _psutil_mswindows.get_system_phymem() |
| 50 total, free, total_pagef, avail_pagef, total_virt, free_virt, percent = all |
| 51 used = total - free |
| 52 return ntuple_sysmeminfo(total, used, free, round(percent, 1)) |
38 | 53 |
39 def used_phymem(): | 54 def virtmem_usage(): |
40 "Return the amount of physical memory currently in use on the system, in byt
es." | 55 """Virtual system memory as a (total, used, free) tuple.""" |
41 return TOTAL_PHYMEM - _psutil_mswindows.get_avail_phymem() | 56 all = _psutil_mswindows.get_system_phymem() |
| 57 total_virt = all[4] |
| 58 free_virt = all[5] |
| 59 used = total_virt - free_virt |
| 60 percent = usage_percent(used, total_virt, _round=1) |
| 61 return ntuple_sysmeminfo(total_virt, used, free_virt, percent) |
42 | 62 |
43 def total_virtmem(): | 63 def get_disk_usage(path): |
44 "Return the amount of total virtual memory available on the system, in bytes
." | 64 """Return disk usage associated with path.""" |
45 return _psutil_mswindows.get_total_virtmem() | 65 try: |
| 66 total, free = _psutil_mswindows.get_disk_usage(path) |
| 67 except WindowsError, err: |
| 68 if not os.path.exists(path): |
| 69 raise OSError(errno.ENOENT, "No such file or directory: '%s'" % path
) |
| 70 raise |
| 71 used = total - free |
| 72 percent = usage_percent(used, total, _round=1) |
| 73 return ntuple_diskinfo(total, used, free, percent) |
46 | 74 |
47 def avail_virtmem(): | 75 def disk_partitions(all): |
48 "Return the amount of virtual memory currently in use on the system, in byte
s." | 76 """Return disk partitions.""" |
49 return _psutil_mswindows.get_avail_virtmem() | 77 retlist = [] |
| 78 drive_letters = _psutil_mswindows.win32_GetLogicalDriveStrings() |
| 79 for letter in drive_letters: |
| 80 mountpoint = letter |
| 81 type = _psutil_mswindows.win32_GetDriveType(letter) |
| 82 if not os.path.exists(mountpoint): |
| 83 # usually a CD-ROM device with no disk inserted |
| 84 mountpoint = "" |
| 85 if not all: |
| 86 if type not in ('cdrom', 'fixed', 'removable'): |
| 87 continue |
| 88 if not mountpoint: |
| 89 continue |
| 90 ntuple = ntuple_partition(letter, mountpoint, type) |
| 91 retlist.append(ntuple) |
| 92 return retlist |
50 | 93 |
51 def used_virtmem(): | 94 |
52 """Return the amount of used memory currently in use on the system, in bytes
.""" | 95 _cputimes_ntuple = namedtuple('cputimes', 'user system idle') |
53 return _psutil_mswindows.get_total_virtmem() - _psutil_mswindows.get_avail_v
irtmem() | |
54 | 96 |
55 def get_system_cpu_times(): | 97 def get_system_cpu_times(): |
56 """Return a dict representing the following CPU times: user, system, idle.""
" | 98 """Return system CPU times as a named tuple.""" |
57 times = _psutil_mswindows.get_system_cpu_times() | 99 user, system, idle = 0, 0, 0 |
58 return dict(user=times[0], system=times[1], idle=times[2]) | 100 # computes system global times summing each processor value |
| 101 for cpu_time in _psutil_mswindows.get_system_cpu_times(): |
| 102 user += cpu_time[0] |
| 103 system += cpu_time[1] |
| 104 idle += cpu_time[2] |
| 105 return _cputimes_ntuple(user, system, idle) |
59 | 106 |
60 def get_pid_list(): | 107 def get_system_per_cpu_times(): |
61 """Returns a list of PIDs currently running on the system.""" | 108 """Return system per-CPU times as a list of named tuples.""" |
62 return _psutil_mswindows.get_pid_list() | 109 ret = [] |
| 110 for cpu_t in _psutil_mswindows.get_system_cpu_times(): |
| 111 user, system, idle = cpu_t |
| 112 item = _cputimes_ntuple(user, system, idle) |
| 113 ret.append(item) |
| 114 return ret |
63 | 115 |
64 def pid_exists(pid): | 116 get_pid_list = _psutil_mswindows.get_pid_list |
65 return _psutil_mswindows.pid_exists(pid) | 117 pid_exists = _psutil_mswindows.pid_exists |
66 | |
67 | 118 |
68 # --- decorator | 119 # --- decorator |
69 | 120 |
70 def wrap_exceptions(callable): | 121 def wrap_exceptions(callable): |
71 """Call callable into a try/except clause so that if a | 122 """Call callable into a try/except clause so that if a |
72 WindowsError 5 AccessDenied exception is raised we translate it | 123 WindowsError 5 AccessDenied exception is raised we translate it |
73 into psutil.AccessDenied | 124 into psutil.AccessDenied |
74 """ | 125 """ |
75 def wrapper(self, *args, **kwargs): | 126 def wrapper(self, *args, **kwargs): |
76 try: | 127 try: |
77 return callable(self, *args, **kwargs) | 128 return callable(self, *args, **kwargs) |
78 except OSError, err: | 129 except OSError, err: |
79 if err.errno in (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED): | 130 if err.errno in (errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED): |
80 raise AccessDenied(self.pid, self._process_name) | 131 raise AccessDenied(self.pid, self._process_name) |
81 if err.errno == errno.ESRCH: | 132 if err.errno == errno.ESRCH: |
82 raise NoSuchProcess(self.pid, self._process_name) | 133 raise NoSuchProcess(self.pid, self._process_name) |
83 raise | 134 raise |
84 return wrapper | 135 return wrapper |
85 | 136 |
86 | 137 |
87 class WindowsProcess(object): | 138 class Process(object): |
88 """Wrapper class around underlying C implementation.""" | 139 """Wrapper class around underlying C implementation.""" |
89 | 140 |
90 _meminfo_ntuple = namedtuple('meminfo', 'rss vms') | |
91 _cputimes_ntuple = namedtuple('cputimes', 'user system') | |
92 _openfile_ntuple = namedtuple('openfile', 'path fd') | |
93 _connection_ntuple = namedtuple('connection', 'fd family type local_address
' | |
94 'remote_address status') | |
95 __slots__ = ["pid", "_process_name"] | 141 __slots__ = ["pid", "_process_name"] |
96 | 142 |
97 def __init__(self, pid): | 143 def __init__(self, pid): |
98 self.pid = pid | 144 self.pid = pid |
99 self._process_name = None | 145 self._process_name = None |
100 | 146 |
101 | 147 |
102 @wrap_exceptions | 148 @wrap_exceptions |
103 def get_process_name(self): | 149 def get_process_name(self): |
104 """Return process name as a string of limited len (15).""" | 150 """Return process name as a string of limited len (15).""" |
105 return _psutil_mswindows.get_process_name(self.pid) | 151 return _psutil_mswindows.get_process_name(self.pid) |
106 | 152 |
107 def get_process_exe(self): | 153 def get_process_exe(self): |
108 # no such thing as "exe" on BSD; it will maybe be determined | 154 # no such thing as "exe" on Windows; it will maybe be determined |
109 # later from cmdline[0] | 155 # later from cmdline[0] |
110 if not pid_exists(self.pid): | 156 if not pid_exists(self.pid): |
111 raise NoSuchProcess(self.pid, self._process_name) | 157 raise NoSuchProcess(self.pid, self._process_name) |
| 158 if self.pid in (0, 4): |
| 159 raise AccessDenied(self.pid, self._process_name) |
112 return "" | 160 return "" |
113 | 161 |
114 @wrap_exceptions | 162 @wrap_exceptions |
115 def get_process_cmdline(self): | 163 def get_process_cmdline(self): |
116 """Return process cmdline as a list of arguments.""" | 164 """Return process cmdline as a list of arguments.""" |
117 return _psutil_mswindows.get_process_cmdline(self.pid) | 165 return _psutil_mswindows.get_process_cmdline(self.pid) |
118 | 166 |
119 @wrap_exceptions | 167 @wrap_exceptions |
120 def get_process_ppid(self): | 168 def get_process_ppid(self): |
121 """Return process parent pid.""" | 169 """Return process parent pid.""" |
122 return _psutil_mswindows.get_process_ppid(self.pid) | 170 return _psutil_mswindows.get_process_ppid(self.pid) |
123 | 171 |
124 def get_process_uid(self): | |
125 # no such thing as uid on Windows | |
126 if not pid_exists(self.pid): | |
127 raise NoSuchProcess(self.pid, self._process_name) | |
128 return -1 | |
129 | |
130 def get_process_gid(self): | |
131 # no such thing as gid on Windows | |
132 if not pid_exists(self.pid): | |
133 raise NoSuchProcess(self.pid, self._process_name) | |
134 return -1 | |
135 | |
136 @wrap_exceptions | 172 @wrap_exceptions |
137 def get_memory_info(self): | 173 def get_memory_info(self): |
138 """Returns a tuple or RSS/VMS memory usage in bytes.""" | 174 """Returns a tuple or RSS/VMS memory usage in bytes.""" |
139 # special case for 0 (kernel processes) PID | 175 # special case for 0 (kernel processes) PID |
140 if self.pid == 0: | 176 if self.pid == 0: |
141 return self._meminfo_ntuple(0, 0) | 177 return ntuple_meminfo(0, 0) |
142 rss, vms = _psutil_mswindows.get_memory_info(self.pid) | 178 rss, vms = _psutil_mswindows.get_memory_info(self.pid) |
143 return self._meminfo_ntuple(rss, vms) | 179 return ntuple_meminfo(rss, vms) |
144 | 180 |
145 @wrap_exceptions | 181 @wrap_exceptions |
146 def kill_process(self): | 182 def kill_process(self): |
147 """Terminates the process with the given PID.""" | 183 """Terminates the process with the given PID.""" |
148 return _psutil_mswindows.kill_process(self.pid) | 184 return _psutil_mswindows.kill_process(self.pid) |
149 | 185 |
150 @wrap_exceptions | 186 @wrap_exceptions |
| 187 def process_wait(self, timeout=None): |
| 188 if timeout is None: |
| 189 timeout = INFINITE |
| 190 else: |
| 191 # WaitForSingleObject() expects time in milliseconds |
| 192 timeout = int(timeout * 1000) |
| 193 ret = _psutil_mswindows.process_wait(self.pid, timeout) |
| 194 if ret == WAIT_TIMEOUT: |
| 195 raise TimeoutExpired(self.pid, self._process_name) |
| 196 return ret |
| 197 |
| 198 @wrap_exceptions |
151 def get_process_username(self): | 199 def get_process_username(self): |
152 """Return the name of the user that owns the process""" | 200 """Return the name of the user that owns the process""" |
153 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: | 201 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: |
154 return 'NT AUTHORITY\\SYSTEM' | 202 return 'NT AUTHORITY\\SYSTEM' |
155 return _psutil_mswindows.get_process_username(self.pid); | 203 return _psutil_mswindows.get_process_username(self.pid); |
156 | 204 |
157 @wrap_exceptions | 205 @wrap_exceptions |
158 def get_process_create_time(self): | 206 def get_process_create_time(self): |
159 # special case for kernel process PIDs; return system uptime | 207 # special case for kernel process PIDs; return system boot time |
160 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: | 208 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: |
161 return _UPTIME | 209 return BOOT_TIME |
162 return _psutil_mswindows.get_process_create_time(self.pid) | 210 return _psutil_mswindows.get_process_create_time(self.pid) |
163 | 211 |
164 @wrap_exceptions | 212 @wrap_exceptions |
165 def get_process_num_threads(self): | 213 def get_process_num_threads(self): |
166 return _psutil_mswindows.get_process_num_threads(self.pid) | 214 return _psutil_mswindows.get_process_num_threads(self.pid) |
167 | 215 |
168 @wrap_exceptions | 216 @wrap_exceptions |
| 217 def get_process_threads(self): |
| 218 rawlist = _psutil_mswindows.get_process_threads(self.pid) |
| 219 retlist = [] |
| 220 for thread_id, utime, stime in rawlist: |
| 221 ntuple = ntuple_thread(thread_id, utime, stime) |
| 222 retlist.append(ntuple) |
| 223 return retlist |
| 224 |
| 225 @wrap_exceptions |
169 def get_cpu_times(self): | 226 def get_cpu_times(self): |
170 user, system = _psutil_mswindows.get_process_cpu_times(self.pid) | 227 user, system = _psutil_mswindows.get_process_cpu_times(self.pid) |
171 return self._cputimes_ntuple(user, system) | 228 return ntuple_cputimes(user, system) |
172 | 229 |
| 230 @wrap_exceptions |
173 def suspend_process(self): | 231 def suspend_process(self): |
174 return _psutil_mswindows.suspend_process(self.pid) | 232 return _psutil_mswindows.suspend_process(self.pid) |
175 | 233 |
| 234 @wrap_exceptions |
176 def resume_process(self): | 235 def resume_process(self): |
177 return _psutil_mswindows.resume_process(self.pid) | 236 return _psutil_mswindows.resume_process(self.pid) |
178 | 237 |
179 @wrap_exceptions | 238 @wrap_exceptions |
180 def get_process_cwd(self): | 239 def get_process_cwd(self): |
181 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: | 240 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: |
182 return '' | 241 raise AccessDenied(self.pid, self._process_name) |
183 # return a normalized pathname since the native C function appends | 242 # return a normalized pathname since the native C function appends |
184 # "\\" at the and of the path | 243 # "\\" at the and of the path |
185 path = _psutil_mswindows.get_process_cwd(self.pid) | 244 path = _psutil_mswindows.get_process_cwd(self.pid) |
186 return os.path.normpath(path) | 245 return os.path.normpath(path) |
187 | 246 |
188 @wrap_exceptions | 247 @wrap_exceptions |
189 def get_open_files(self): | 248 def get_open_files(self): |
190 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: | 249 if self.pid in (0, 4) or self.pid == 8 and _WIN2000: |
191 return [] | 250 return [] |
192 retlist = [] | 251 retlist = [] |
193 # Filenames come in in native format like: | 252 # Filenames come in in native format like: |
194 # "\Device\HarddiskVolume1\Windows\systemew\file.txt" | 253 # "\Device\HarddiskVolume1\Windows\systemew\file.txt" |
195 # Convert the first part in the corresponding drive letter | 254 # Convert the first part in the corresponding drive letter |
196 # (e.g. "C:\") by using Windows's QueryDosDevice() | 255 # (e.g. "C:\") by using Windows's QueryDosDevice() |
197 raw_file_names = _psutil_mswindows.get_process_open_files(self.pid) | 256 raw_file_names = _psutil_mswindows.get_process_open_files(self.pid) |
198 for file in raw_file_names: | 257 for file in raw_file_names: |
199 if sys.version_info >= (3,): | 258 if sys.version_info >= (3,): |
200 file = file.decode('utf8') | 259 file = file.decode('utf8') |
201 if file.startswith('\\Device\\'): | 260 if file.startswith('\\Device\\'): |
202 rawdrive = '\\'.join(file.split('\\')[:3]) | 261 rawdrive = '\\'.join(file.split('\\')[:3]) |
203 driveletter = _psutil_mswindows._QueryDosDevice(rawdrive) | 262 driveletter = _psutil_mswindows.win32_QueryDosDevice(rawdrive) |
204 file = file.replace(rawdrive, driveletter) | 263 file = file.replace(rawdrive, driveletter) |
205 if os.path.isfile(file) and file not in retlist: | 264 if os.path.isfile(file) and file not in retlist: |
206 ntuple = self._openfile_ntuple(file, -1) | 265 ntuple = ntuple_openfile(file, -1) |
207 retlist.append(ntuple) | 266 retlist.append(ntuple) |
208 return retlist | 267 return retlist |
209 | 268 |
210 @wrap_exceptions | 269 @wrap_exceptions |
211 def get_connections(self): | 270 def get_connections(self): |
212 retlist = _psutil_mswindows.get_process_connections(self.pid) | 271 retlist = _psutil_mswindows.get_process_connections(self.pid) |
213 return [self._connection_ntuple(*conn) for conn in retlist] | 272 return [ntuple_connection(*conn) for conn in retlist] |
214 | 273 |
215 PlatformProcess = WindowsProcess | 274 @wrap_exceptions |
| 275 def get_process_nice(self): |
| 276 return _psutil_mswindows.get_process_priority(self.pid) |
| 277 |
| 278 @wrap_exceptions |
| 279 def set_process_nice(self, value): |
| 280 return _psutil_mswindows.set_process_priority(self.pid, value) |
| 281 |
| 282 @wrap_exceptions |
| 283 def get_process_io_counters(self): |
| 284 rc, wc, rb, wb =_psutil_mswindows.get_process_io_counters(self.pid) |
| 285 return ntuple_io(rc, wc, rb, wb) |
| 286 |
| 287 @wrap_exceptions |
| 288 def get_process_status(self): |
| 289 suspended = _psutil_mswindows.is_process_suspended(self.pid) |
| 290 if suspended: |
| 291 return STATUS_STOPPED |
| 292 else: |
| 293 return STATUS_RUNNING |
OLD | NEW |