Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/psutil/__init__.py: 26%

943 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1# -*- coding: utf-8 -*- 

2 

3# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. 

4# Use of this source code is governed by a BSD-style license that can be 

5# found in the LICENSE file. 

6 

7"""psutil is a cross-platform library for retrieving information on 

8running processes and system utilization (CPU, memory, disks, network, 

9sensors) in Python. Supported platforms: 

10 

11 - Linux 

12 - Windows 

13 - macOS 

14 - FreeBSD 

15 - OpenBSD 

16 - NetBSD 

17 - Sun Solaris 

18 - AIX 

19 

20Works with Python versions 2.7 and 3.4+. 

21""" 

22 

23from __future__ import division 

24 

25import collections 

26import contextlib 

27import datetime 

28import functools 

29import os 

30import signal 

31import subprocess 

32import sys 

33import threading 

34import time 

35 

36 

37try: 

38 import pwd 

39except ImportError: 

40 pwd = None 

41 

42from . import _common 

43from ._common import AIX 

44from ._common import BSD 

45from ._common import CONN_CLOSE 

46from ._common import CONN_CLOSE_WAIT 

47from ._common import CONN_CLOSING 

48from ._common import CONN_ESTABLISHED 

49from ._common import CONN_FIN_WAIT1 

50from ._common import CONN_FIN_WAIT2 

51from ._common import CONN_LAST_ACK 

52from ._common import CONN_LISTEN 

53from ._common import CONN_NONE 

54from ._common import CONN_SYN_RECV 

55from ._common import CONN_SYN_SENT 

56from ._common import CONN_TIME_WAIT 

57from ._common import FREEBSD # NOQA 

58from ._common import LINUX 

59from ._common import MACOS 

60from ._common import NETBSD # NOQA 

61from ._common import NIC_DUPLEX_FULL 

62from ._common import NIC_DUPLEX_HALF 

63from ._common import NIC_DUPLEX_UNKNOWN 

64from ._common import OPENBSD # NOQA 

65from ._common import OSX # deprecated alias 

66from ._common import POSIX # NOQA 

67from ._common import POWER_TIME_UNKNOWN 

68from ._common import POWER_TIME_UNLIMITED 

69from ._common import STATUS_DEAD 

70from ._common import STATUS_DISK_SLEEP 

71from ._common import STATUS_IDLE 

72from ._common import STATUS_LOCKED 

73from ._common import STATUS_PARKED 

74from ._common import STATUS_RUNNING 

75from ._common import STATUS_SLEEPING 

76from ._common import STATUS_STOPPED 

77from ._common import STATUS_TRACING_STOP 

78from ._common import STATUS_WAITING 

79from ._common import STATUS_WAKING 

80from ._common import STATUS_ZOMBIE 

81from ._common import SUNOS 

82from ._common import WINDOWS 

83from ._common import AccessDenied 

84from ._common import Error 

85from ._common import NoSuchProcess 

86from ._common import TimeoutExpired 

87from ._common import ZombieProcess 

88from ._common import memoize_when_activated 

89from ._common import wrap_numbers as _wrap_numbers 

90from ._compat import PY3 as _PY3 

91from ._compat import PermissionError 

92from ._compat import ProcessLookupError 

93from ._compat import SubprocessTimeoutExpired as _SubprocessTimeoutExpired 

94from ._compat import long 

95 

96 

97if LINUX: 

98 # This is public API and it will be retrieved from _pslinux.py 

99 # via sys.modules. 

100 PROCFS_PATH = "/proc" 

101 

102 from . import _pslinux as _psplatform 

103 from ._pslinux import IOPRIO_CLASS_BE # NOQA 

104 from ._pslinux import IOPRIO_CLASS_IDLE # NOQA 

105 from ._pslinux import IOPRIO_CLASS_NONE # NOQA 

106 from ._pslinux import IOPRIO_CLASS_RT # NOQA 

107 

108elif WINDOWS: 

109 from . import _pswindows as _psplatform 

110 from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # NOQA 

111 from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # NOQA 

112 from ._psutil_windows import HIGH_PRIORITY_CLASS # NOQA 

113 from ._psutil_windows import IDLE_PRIORITY_CLASS # NOQA 

114 from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA 

115 from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA 

116 from ._pswindows import CONN_DELETE_TCB # NOQA 

117 from ._pswindows import IOPRIO_HIGH # NOQA 

118 from ._pswindows import IOPRIO_LOW # NOQA 

119 from ._pswindows import IOPRIO_NORMAL # NOQA 

120 from ._pswindows import IOPRIO_VERYLOW # NOQA 

121 

122elif MACOS: 

123 from . import _psosx as _psplatform 

124 

125elif BSD: 

126 from . import _psbsd as _psplatform 

127 

128elif SUNOS: 

129 from . import _pssunos as _psplatform 

130 from ._pssunos import CONN_BOUND # NOQA 

131 from ._pssunos import CONN_IDLE # NOQA 

132 

133 # This is public writable API which is read from _pslinux.py and 

134 # _pssunos.py via sys.modules. 

135 PROCFS_PATH = "/proc" 

136 

137elif AIX: 

138 from . import _psaix as _psplatform 

139 

140 # This is public API and it will be retrieved from _pslinux.py 

141 # via sys.modules. 

142 PROCFS_PATH = "/proc" 

143 

144else: # pragma: no cover 

145 raise NotImplementedError('platform %s is not supported' % sys.platform) 

146 

147 

148__all__ = [ 

149 # exceptions 

150 "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", 

151 "TimeoutExpired", 

152 

153 # constants 

154 "version_info", "__version__", 

155 

156 "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", 

157 "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", 

158 "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", 

159 "STATUS_PARKED", 

160 

161 "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", 

162 "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", 

163 "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", 

164 # "CONN_IDLE", "CONN_BOUND", 

165 

166 "AF_LINK", 

167 

168 "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", 

169 

170 "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED", 

171 

172 "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", 

173 "SUNOS", "WINDOWS", "AIX", 

174 

175 # "RLIM_INFINITY", "RLIMIT_AS", "RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA", 

176 # "RLIMIT_FSIZE", "RLIMIT_LOCKS", "RLIMIT_MEMLOCK", "RLIMIT_NOFILE", 

177 # "RLIMIT_NPROC", "RLIMIT_RSS", "RLIMIT_STACK", "RLIMIT_MSGQUEUE", 

178 # "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIMIT_SIGPENDING", 

179 

180 # classes 

181 "Process", "Popen", 

182 

183 # functions 

184 "pid_exists", "pids", "process_iter", "wait_procs", # proc 

185 "virtual_memory", "swap_memory", # memory 

186 "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu 

187 "cpu_stats", # "cpu_freq", "getloadavg" 

188 "net_io_counters", "net_connections", "net_if_addrs", # network 

189 "net_if_stats", 

190 "disk_io_counters", "disk_partitions", "disk_usage", # disk 

191 # "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors 

192 "users", "boot_time", # others 

193] 

194 

195 

196__all__.extend(_psplatform.__extra__all__) 

197 

198# Linux, FreeBSD 

199if hasattr(_psplatform.Process, "rlimit"): 

200 # Populate global namespace with RLIM* constants. 

201 from . import _psutil_posix 

202 

203 _globals = globals() 

204 _name = None 

205 for _name in dir(_psutil_posix): 

206 if _name.startswith('RLIM') and _name.isupper(): 

207 _globals[_name] = getattr(_psutil_posix, _name) 

208 __all__.append(_name) 

209 del _globals, _name 

210 

211AF_LINK = _psplatform.AF_LINK 

212 

213__author__ = "Giampaolo Rodola'" 

214__version__ = "5.9.4" 

215version_info = tuple([int(num) for num in __version__.split('.')]) 

216 

217_timer = getattr(time, 'monotonic', time.time) 

218_TOTAL_PHYMEM = None 

219_LOWEST_PID = None 

220_SENTINEL = object() 

221 

222# Sanity check in case the user messed up with psutil installation 

223# or did something weird with sys.path. In this case we might end 

224# up importing a python module using a C extension module which 

225# was compiled for a different version of psutil. 

226# We want to prevent that by failing sooner rather than later. 

227# See: https://github.com/giampaolo/psutil/issues/564 

228if (int(__version__.replace('.', '')) != 

229 getattr(_psplatform.cext, 'version', None)): 

230 msg = "version conflict: %r C extension module was built for another " \ 

231 "version of psutil" % _psplatform.cext.__file__ 

232 if hasattr(_psplatform.cext, 'version'): 

233 msg += " (%s instead of %s)" % ( 

234 '.'.join([x for x in str(_psplatform.cext.version)]), __version__) 

235 else: 

236 msg += " (different than %s)" % __version__ 

237 msg += "; you may try to 'pip uninstall psutil', manually remove %s" % ( 

238 getattr(_psplatform.cext, "__file__", 

239 "the existing psutil install directory")) 

240 msg += " or clean the virtual env somehow, then reinstall" 

241 raise ImportError(msg) 

242 

243 

244# ===================================================================== 

245# --- Utils 

246# ===================================================================== 

247 

248 

249if hasattr(_psplatform, 'ppid_map'): 

250 # Faster version (Windows and Linux). 

251 _ppid_map = _psplatform.ppid_map 

252else: # pragma: no cover 

253 def _ppid_map(): 

254 """Return a {pid: ppid, ...} dict for all running processes in 

255 one shot. Used to speed up Process.children(). 

256 """ 

257 ret = {} 

258 for pid in pids(): 

259 try: 

260 ret[pid] = _psplatform.Process(pid).ppid() 

261 except (NoSuchProcess, ZombieProcess): 

262 pass 

263 return ret 

264 

265 

266def _assert_pid_not_reused(fun): 

267 """Decorator which raises NoSuchProcess in case a process is no 

268 longer running or its PID has been reused. 

269 """ 

270 @functools.wraps(fun) 

271 def wrapper(self, *args, **kwargs): 

272 if not self.is_running(): 

273 if self._pid_reused: 

274 msg = "process no longer exists and its PID has been reused" 

275 else: 

276 msg = None 

277 raise NoSuchProcess(self.pid, self._name, msg=msg) 

278 return fun(self, *args, **kwargs) 

279 return wrapper 

280 

281 

282def _pprint_secs(secs): 

283 """Format seconds in a human readable form.""" 

284 now = time.time() 

285 secs_ago = int(now - secs) 

286 if secs_ago < 60 * 60 * 24: 

287 fmt = "%H:%M:%S" 

288 else: 

289 fmt = "%Y-%m-%d %H:%M:%S" 

290 return datetime.datetime.fromtimestamp(secs).strftime(fmt) 

291 

292 

293# ===================================================================== 

294# --- Process class 

295# ===================================================================== 

296 

297 

298class Process(object): 

299 """Represents an OS process with the given PID. 

300 If PID is omitted current process PID (os.getpid()) is used. 

301 Raise NoSuchProcess if PID does not exist. 

302 

303 Note that most of the methods of this class do not make sure 

304 the PID of the process being queried has been reused over time. 

305 That means you might end up retrieving an information referring 

306 to another process in case the original one this instance 

307 refers to is gone in the meantime. 

308 

309 The only exceptions for which process identity is pre-emptively 

310 checked and guaranteed are: 

311 

312 - parent() 

313 - children() 

314 - nice() (set) 

315 - ionice() (set) 

316 - rlimit() (set) 

317 - cpu_affinity (set) 

318 - suspend() 

319 - resume() 

320 - send_signal() 

321 - terminate() 

322 - kill() 

323 

324 To prevent this problem for all other methods you can: 

325 - use is_running() before querying the process 

326 - if you're continuously iterating over a set of Process 

327 instances use process_iter() which pre-emptively checks 

328 process identity for every yielded instance 

329 """ 

330 

331 def __init__(self, pid=None): 

332 self._init(pid) 

333 

334 def _init(self, pid, _ignore_nsp=False): 

335 if pid is None: 

336 pid = os.getpid() 

337 else: 

338 if not _PY3 and not isinstance(pid, (int, long)): 

339 raise TypeError('pid must be an integer (got %r)' % pid) 

340 if pid < 0: 

341 raise ValueError('pid must be a positive integer (got %s)' 

342 % pid) 

343 self._pid = pid 

344 self._name = None 

345 self._exe = None 

346 self._create_time = None 

347 self._gone = False 

348 self._pid_reused = False 

349 self._hash = None 

350 self._lock = threading.RLock() 

351 # used for caching on Windows only (on POSIX ppid may change) 

352 self._ppid = None 

353 # platform-specific modules define an _psplatform.Process 

354 # implementation class 

355 self._proc = _psplatform.Process(pid) 

356 self._last_sys_cpu_times = None 

357 self._last_proc_cpu_times = None 

358 self._exitcode = _SENTINEL 

359 # cache creation time for later use in is_running() method 

360 try: 

361 self.create_time() 

362 except AccessDenied: 

363 # We should never get here as AFAIK we're able to get 

364 # process creation time on all platforms even as a 

365 # limited user. 

366 pass 

367 except ZombieProcess: 

368 # Zombies can still be queried by this class (although 

369 # not always) and pids() return them so just go on. 

370 pass 

371 except NoSuchProcess: 

372 if not _ignore_nsp: 

373 raise NoSuchProcess(pid, msg='process PID not found') 

374 else: 

375 self._gone = True 

376 # This pair is supposed to identify a Process instance 

377 # univocally over time (the PID alone is not enough as 

378 # it might refer to a process whose PID has been reused). 

379 # This will be used later in __eq__() and is_running(). 

380 self._ident = (self.pid, self._create_time) 

381 

382 def __str__(self): 

383 info = collections.OrderedDict() 

384 info["pid"] = self.pid 

385 if self._name: 

386 info['name'] = self._name 

387 with self.oneshot(): 

388 try: 

389 info["name"] = self.name() 

390 info["status"] = self.status() 

391 except ZombieProcess: 

392 info["status"] = "zombie" 

393 except NoSuchProcess: 

394 info["status"] = "terminated" 

395 except AccessDenied: 

396 pass 

397 if self._exitcode not in (_SENTINEL, None): 

398 info["exitcode"] = self._exitcode 

399 if self._create_time: 

400 info['started'] = _pprint_secs(self._create_time) 

401 return "%s.%s(%s)" % ( 

402 self.__class__.__module__, 

403 self.__class__.__name__, 

404 ", ".join(["%s=%r" % (k, v) for k, v in info.items()])) 

405 

406 __repr__ = __str__ 

407 

408 def __eq__(self, other): 

409 # Test for equality with another Process object based 

410 # on PID and creation time. 

411 if not isinstance(other, Process): 

412 return NotImplemented 

413 return self._ident == other._ident 

414 

415 def __ne__(self, other): 

416 return not self == other 

417 

418 def __hash__(self): 

419 if self._hash is None: 

420 self._hash = hash(self._ident) 

421 return self._hash 

422 

423 @property 

424 def pid(self): 

425 """The process PID.""" 

426 return self._pid 

427 

428 # --- utility methods 

429 

430 @contextlib.contextmanager 

431 def oneshot(self): 

432 """Utility context manager which considerably speeds up the 

433 retrieval of multiple process information at the same time. 

434 

435 Internally different process info (e.g. name, ppid, uids, 

436 gids, ...) may be fetched by using the same routine, but 

437 only one information is returned and the others are discarded. 

438 When using this context manager the internal routine is 

439 executed once (in the example below on name()) and the 

440 other info are cached. 

441 

442 The cache is cleared when exiting the context manager block. 

443 The advice is to use this every time you retrieve more than 

444 one information about the process. If you're lucky, you'll 

445 get a hell of a speedup. 

446 

447 >>> import psutil 

448 >>> p = psutil.Process() 

449 >>> with p.oneshot(): 

450 ... p.name() # collect multiple info 

451 ... p.cpu_times() # return cached value 

452 ... p.cpu_percent() # return cached value 

453 ... p.create_time() # return cached value 

454 ... 

455 >>> 

456 """ 

457 with self._lock: 

458 if hasattr(self, "_cache"): 

459 # NOOP: this covers the use case where the user enters the 

460 # context twice: 

461 # 

462 # >>> with p.oneshot(): 

463 # ... with p.oneshot(): 

464 # ... 

465 # 

466 # Also, since as_dict() internally uses oneshot() 

467 # I expect that the code below will be a pretty common 

468 # "mistake" that the user will make, so let's guard 

469 # against that: 

470 # 

471 # >>> with p.oneshot(): 

472 # ... p.as_dict() 

473 # ... 

474 yield 

475 else: 

476 try: 

477 # cached in case cpu_percent() is used 

478 self.cpu_times.cache_activate(self) 

479 # cached in case memory_percent() is used 

480 self.memory_info.cache_activate(self) 

481 # cached in case parent() is used 

482 self.ppid.cache_activate(self) 

483 # cached in case username() is used 

484 if POSIX: 

485 self.uids.cache_activate(self) 

486 # specific implementation cache 

487 self._proc.oneshot_enter() 

488 yield 

489 finally: 

490 self.cpu_times.cache_deactivate(self) 

491 self.memory_info.cache_deactivate(self) 

492 self.ppid.cache_deactivate(self) 

493 if POSIX: 

494 self.uids.cache_deactivate(self) 

495 self._proc.oneshot_exit() 

496 

497 def as_dict(self, attrs=None, ad_value=None): 

498 """Utility method returning process information as a 

499 hashable dictionary. 

500 If *attrs* is specified it must be a list of strings 

501 reflecting available Process class' attribute names 

502 (e.g. ['cpu_times', 'name']) else all public (read 

503 only) attributes are assumed. 

504 *ad_value* is the value which gets assigned in case 

505 AccessDenied or ZombieProcess exception is raised when 

506 retrieving that particular process information. 

507 """ 

508 valid_names = _as_dict_attrnames 

509 if attrs is not None: 

510 if not isinstance(attrs, (list, tuple, set, frozenset)): 

511 raise TypeError("invalid attrs type %s" % type(attrs)) 

512 attrs = set(attrs) 

513 invalid_names = attrs - valid_names 

514 if invalid_names: 

515 raise ValueError("invalid attr name%s %s" % ( 

516 "s" if len(invalid_names) > 1 else "", 

517 ", ".join(map(repr, invalid_names)))) 

518 

519 retdict = dict() 

520 ls = attrs or valid_names 

521 with self.oneshot(): 

522 for name in ls: 

523 try: 

524 if name == 'pid': 

525 ret = self.pid 

526 else: 

527 meth = getattr(self, name) 

528 ret = meth() 

529 except (AccessDenied, ZombieProcess): 

530 ret = ad_value 

531 except NotImplementedError: 

532 # in case of not implemented functionality (may happen 

533 # on old or exotic systems) we want to crash only if 

534 # the user explicitly asked for that particular attr 

535 if attrs: 

536 raise 

537 continue 

538 retdict[name] = ret 

539 return retdict 

540 

541 def parent(self): 

542 """Return the parent process as a Process object pre-emptively 

543 checking whether PID has been reused. 

544 If no parent is known return None. 

545 """ 

546 lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0] 

547 if self.pid == lowest_pid: 

548 return None 

549 ppid = self.ppid() 

550 if ppid is not None: 

551 ctime = self.create_time() 

552 try: 

553 parent = Process(ppid) 

554 if parent.create_time() <= ctime: 

555 return parent 

556 # ...else ppid has been reused by another process 

557 except NoSuchProcess: 

558 pass 

559 

560 def parents(self): 

561 """Return the parents of this process as a list of Process 

562 instances. If no parents are known return an empty list. 

563 """ 

564 parents = [] 

565 proc = self.parent() 

566 while proc is not None: 

567 parents.append(proc) 

568 proc = proc.parent() 

569 return parents 

570 

571 def is_running(self): 

572 """Return whether this process is running. 

573 It also checks if PID has been reused by another process in 

574 which case return False. 

575 """ 

576 if self._gone or self._pid_reused: 

577 return False 

578 try: 

579 # Checking if PID is alive is not enough as the PID might 

580 # have been reused by another process: we also want to 

581 # verify process identity. 

582 # Process identity / uniqueness over time is guaranteed by 

583 # (PID + creation time) and that is verified in __eq__. 

584 self._pid_reused = self != Process(self.pid) 

585 return not self._pid_reused 

586 except ZombieProcess: 

587 # We should never get here as it's already handled in 

588 # Process.__init__; here just for extra safety. 

589 return True 

590 except NoSuchProcess: 

591 self._gone = True 

592 return False 

593 

594 # --- actual API 

595 

596 @memoize_when_activated 

597 def ppid(self): 

598 """The process parent PID. 

599 On Windows the return value is cached after first call. 

600 """ 

601 # On POSIX we don't want to cache the ppid as it may unexpectedly 

602 # change to 1 (init) in case this process turns into a zombie: 

603 # https://github.com/giampaolo/psutil/issues/321 

604 # http://stackoverflow.com/questions/356722/ 

605 

606 # XXX should we check creation time here rather than in 

607 # Process.parent()? 

608 if POSIX: 

609 return self._proc.ppid() 

610 else: # pragma: no cover 

611 self._ppid = self._ppid or self._proc.ppid() 

612 return self._ppid 

613 

614 def name(self): 

615 """The process name. The return value is cached after first call.""" 

616 # Process name is only cached on Windows as on POSIX it may 

617 # change, see: 

618 # https://github.com/giampaolo/psutil/issues/692 

619 if WINDOWS and self._name is not None: 

620 return self._name 

621 name = self._proc.name() 

622 if POSIX and len(name) >= 15: 

623 # On UNIX the name gets truncated to the first 15 characters. 

624 # If it matches the first part of the cmdline we return that 

625 # one instead because it's usually more explicative. 

626 # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". 

627 try: 

628 cmdline = self.cmdline() 

629 except AccessDenied: 

630 pass 

631 else: 

632 if cmdline: 

633 extended_name = os.path.basename(cmdline[0]) 

634 if extended_name.startswith(name): 

635 name = extended_name 

636 self._name = name 

637 self._proc._name = name 

638 return name 

639 

640 def exe(self): 

641 """The process executable as an absolute path. 

642 May also be an empty string. 

643 The return value is cached after first call. 

644 """ 

645 def guess_it(fallback): 

646 # try to guess exe from cmdline[0] in absence of a native 

647 # exe representation 

648 cmdline = self.cmdline() 

649 if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): 

650 exe = cmdline[0] # the possible exe 

651 # Attempt to guess only in case of an absolute path. 

652 # It is not safe otherwise as the process might have 

653 # changed cwd. 

654 if (os.path.isabs(exe) and 

655 os.path.isfile(exe) and 

656 os.access(exe, os.X_OK)): 

657 return exe 

658 if isinstance(fallback, AccessDenied): 

659 raise fallback 

660 return fallback 

661 

662 if self._exe is None: 

663 try: 

664 exe = self._proc.exe() 

665 except AccessDenied as err: 

666 return guess_it(fallback=err) 

667 else: 

668 if not exe: 

669 # underlying implementation can legitimately return an 

670 # empty string; if that's the case we don't want to 

671 # raise AD while guessing from the cmdline 

672 try: 

673 exe = guess_it(fallback=exe) 

674 except AccessDenied: 

675 pass 

676 self._exe = exe 

677 return self._exe 

678 

679 def cmdline(self): 

680 """The command line this process has been called with.""" 

681 return self._proc.cmdline() 

682 

683 def status(self): 

684 """The process current status as a STATUS_* constant.""" 

685 try: 

686 return self._proc.status() 

687 except ZombieProcess: 

688 return STATUS_ZOMBIE 

689 

690 def username(self): 

691 """The name of the user that owns the process. 

692 On UNIX this is calculated by using *real* process uid. 

693 """ 

694 if POSIX: 

695 if pwd is None: 

696 # might happen if python was installed from sources 

697 raise ImportError( 

698 "requires pwd module shipped with standard python") 

699 real_uid = self.uids().real 

700 try: 

701 return pwd.getpwuid(real_uid).pw_name 

702 except KeyError: 

703 # the uid can't be resolved by the system 

704 return str(real_uid) 

705 else: 

706 return self._proc.username() 

707 

708 def create_time(self): 

709 """The process creation time as a floating point number 

710 expressed in seconds since the epoch. 

711 The return value is cached after first call. 

712 """ 

713 if self._create_time is None: 

714 self._create_time = self._proc.create_time() 

715 return self._create_time 

716 

717 def cwd(self): 

718 """Process current working directory as an absolute path.""" 

719 return self._proc.cwd() 

720 

721 def nice(self, value=None): 

722 """Get or set process niceness (priority).""" 

723 if value is None: 

724 return self._proc.nice_get() 

725 else: 

726 if not self.is_running(): 

727 raise NoSuchProcess(self.pid, self._name) 

728 self._proc.nice_set(value) 

729 

730 if POSIX: 

731 

732 @memoize_when_activated 

733 def uids(self): 

734 """Return process UIDs as a (real, effective, saved) 

735 namedtuple. 

736 """ 

737 return self._proc.uids() 

738 

739 def gids(self): 

740 """Return process GIDs as a (real, effective, saved) 

741 namedtuple. 

742 """ 

743 return self._proc.gids() 

744 

745 def terminal(self): 

746 """The terminal associated with this process, if any, 

747 else None. 

748 """ 

749 return self._proc.terminal() 

750 

751 def num_fds(self): 

752 """Return the number of file descriptors opened by this 

753 process (POSIX only). 

754 """ 

755 return self._proc.num_fds() 

756 

757 # Linux, BSD, AIX and Windows only 

758 if hasattr(_psplatform.Process, "io_counters"): 

759 

760 def io_counters(self): 

761 """Return process I/O statistics as a 

762 (read_count, write_count, read_bytes, write_bytes) 

763 namedtuple. 

764 Those are the number of read/write calls performed and the 

765 amount of bytes read and written by the process. 

766 """ 

767 return self._proc.io_counters() 

768 

769 # Linux and Windows 

770 if hasattr(_psplatform.Process, "ionice_get"): 

771 

772 def ionice(self, ioclass=None, value=None): 

773 """Get or set process I/O niceness (priority). 

774 

775 On Linux *ioclass* is one of the IOPRIO_CLASS_* constants. 

776 *value* is a number which goes from 0 to 7. The higher the 

777 value, the lower the I/O priority of the process. 

778 

779 On Windows only *ioclass* is used and it can be set to 2 

780 (normal), 1 (low) or 0 (very low). 

781 

782 Available on Linux and Windows > Vista only. 

783 """ 

784 if ioclass is None: 

785 if value is not None: 

786 raise ValueError("'ioclass' argument must be specified") 

787 return self._proc.ionice_get() 

788 else: 

789 return self._proc.ionice_set(ioclass, value) 

790 

791 # Linux / FreeBSD only 

792 if hasattr(_psplatform.Process, "rlimit"): 

793 

794 def rlimit(self, resource, limits=None): 

795 """Get or set process resource limits as a (soft, hard) 

796 tuple. 

797 

798 *resource* is one of the RLIMIT_* constants. 

799 *limits* is supposed to be a (soft, hard) tuple. 

800 

801 See "man prlimit" for further info. 

802 Available on Linux and FreeBSD only. 

803 """ 

804 return self._proc.rlimit(resource, limits) 

805 

806 # Windows, Linux and FreeBSD only 

807 if hasattr(_psplatform.Process, "cpu_affinity_get"): 

808 

809 def cpu_affinity(self, cpus=None): 

810 """Get or set process CPU affinity. 

811 If specified, *cpus* must be a list of CPUs for which you 

812 want to set the affinity (e.g. [0, 1]). 

813 If an empty list is passed, all egible CPUs are assumed 

814 (and set). 

815 (Windows, Linux and BSD only). 

816 """ 

817 if cpus is None: 

818 return sorted(set(self._proc.cpu_affinity_get())) 

819 else: 

820 if not cpus: 

821 if hasattr(self._proc, "_get_eligible_cpus"): 

822 cpus = self._proc._get_eligible_cpus() 

823 else: 

824 cpus = tuple(range(len(cpu_times(percpu=True)))) 

825 self._proc.cpu_affinity_set(list(set(cpus))) 

826 

827 # Linux, FreeBSD, SunOS 

828 if hasattr(_psplatform.Process, "cpu_num"): 

829 

830 def cpu_num(self): 

831 """Return what CPU this process is currently running on. 

832 The returned number should be <= psutil.cpu_count() 

833 and <= len(psutil.cpu_percent(percpu=True)). 

834 It may be used in conjunction with 

835 psutil.cpu_percent(percpu=True) to observe the system 

836 workload distributed across CPUs. 

837 """ 

838 return self._proc.cpu_num() 

839 

840 # All platforms has it, but maybe not in the future. 

841 if hasattr(_psplatform.Process, "environ"): 

842 

843 def environ(self): 

844 """The environment variables of the process as a dict. Note: this 

845 might not reflect changes made after the process started. """ 

846 return self._proc.environ() 

847 

848 if WINDOWS: 

849 

850 def num_handles(self): 

851 """Return the number of handles opened by this process 

852 (Windows only). 

853 """ 

854 return self._proc.num_handles() 

855 

856 def num_ctx_switches(self): 

857 """Return the number of voluntary and involuntary context 

858 switches performed by this process. 

859 """ 

860 return self._proc.num_ctx_switches() 

861 

862 def num_threads(self): 

863 """Return the number of threads used by this process.""" 

864 return self._proc.num_threads() 

865 

866 if hasattr(_psplatform.Process, "threads"): 

867 

868 def threads(self): 

869 """Return threads opened by process as a list of 

870 (id, user_time, system_time) namedtuples representing 

871 thread id and thread CPU times (user/system). 

872 On OpenBSD this method requires root access. 

873 """ 

874 return self._proc.threads() 

875 

876 @_assert_pid_not_reused 

877 def children(self, recursive=False): 

878 """Return the children of this process as a list of Process 

879 instances, pre-emptively checking whether PID has been reused. 

880 If *recursive* is True return all the parent descendants. 

881 

882 Example (A == this process): 

883 

884 A ─┐ 

885 

886 ├─ B (child) ─┐ 

887 │ └─ X (grandchild) ─┐ 

888 │ └─ Y (great grandchild) 

889 ├─ C (child) 

890 └─ D (child) 

891 

892 >>> import psutil 

893 >>> p = psutil.Process() 

894 >>> p.children() 

895 B, C, D 

896 >>> p.children(recursive=True) 

897 B, X, Y, C, D 

898 

899 Note that in the example above if process X disappears 

900 process Y won't be listed as the reference to process A 

901 is lost. 

902 """ 

903 ppid_map = _ppid_map() 

904 ret = [] 

905 if not recursive: 

906 for pid, ppid in ppid_map.items(): 

907 if ppid == self.pid: 

908 try: 

909 child = Process(pid) 

910 # if child happens to be older than its parent 

911 # (self) it means child's PID has been reused 

912 if self.create_time() <= child.create_time(): 

913 ret.append(child) 

914 except (NoSuchProcess, ZombieProcess): 

915 pass 

916 else: 

917 # Construct a {pid: [child pids]} dict 

918 reverse_ppid_map = collections.defaultdict(list) 

919 for pid, ppid in ppid_map.items(): 

920 reverse_ppid_map[ppid].append(pid) 

921 # Recursively traverse that dict, starting from self.pid, 

922 # such that we only call Process() on actual children 

923 seen = set() 

924 stack = [self.pid] 

925 while stack: 

926 pid = stack.pop() 

927 if pid in seen: 

928 # Since pids can be reused while the ppid_map is 

929 # constructed, there may be rare instances where 

930 # there's a cycle in the recorded process "tree". 

931 continue 

932 seen.add(pid) 

933 for child_pid in reverse_ppid_map[pid]: 

934 try: 

935 child = Process(child_pid) 

936 # if child happens to be older than its parent 

937 # (self) it means child's PID has been reused 

938 intime = self.create_time() <= child.create_time() 

939 if intime: 

940 ret.append(child) 

941 stack.append(child_pid) 

942 except (NoSuchProcess, ZombieProcess): 

943 pass 

944 return ret 

945 

946 def cpu_percent(self, interval=None): 

947 """Return a float representing the current process CPU 

948 utilization as a percentage. 

949 

950 When *interval* is 0.0 or None (default) compares process times 

951 to system CPU times elapsed since last call, returning 

952 immediately (non-blocking). That means that the first time 

953 this is called it will return a meaningful 0.0 value. 

954 

955 When *interval* is > 0.0 compares process times to system CPU 

956 times elapsed before and after the interval (blocking). 

957 

958 In this case is recommended for accuracy that this function 

959 be called with at least 0.1 seconds between calls. 

960 

961 A value > 100.0 can be returned in case of processes running 

962 multiple threads on different CPU cores. 

963 

964 The returned value is explicitly NOT split evenly between 

965 all available logical CPUs. This means that a busy loop process 

966 running on a system with 2 logical CPUs will be reported as 

967 having 100% CPU utilization instead of 50%. 

968 

969 Examples: 

970 

971 >>> import psutil 

972 >>> p = psutil.Process(os.getpid()) 

973 >>> # blocking 

974 >>> p.cpu_percent(interval=1) 

975 2.0 

976 >>> # non-blocking (percentage since last call) 

977 >>> p.cpu_percent(interval=None) 

978 2.9 

979 >>> 

980 """ 

981 blocking = interval is not None and interval > 0.0 

982 if interval is not None and interval < 0: 

983 raise ValueError("interval is not positive (got %r)" % interval) 

984 num_cpus = cpu_count() or 1 

985 

986 def timer(): 

987 return _timer() * num_cpus 

988 

989 if blocking: 

990 st1 = timer() 

991 pt1 = self._proc.cpu_times() 

992 time.sleep(interval) 

993 st2 = timer() 

994 pt2 = self._proc.cpu_times() 

995 else: 

996 st1 = self._last_sys_cpu_times 

997 pt1 = self._last_proc_cpu_times 

998 st2 = timer() 

999 pt2 = self._proc.cpu_times() 

1000 if st1 is None or pt1 is None: 

1001 self._last_sys_cpu_times = st2 

1002 self._last_proc_cpu_times = pt2 

1003 return 0.0 

1004 

1005 delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) 

1006 delta_time = st2 - st1 

1007 # reset values for next call in case of interval == None 

1008 self._last_sys_cpu_times = st2 

1009 self._last_proc_cpu_times = pt2 

1010 

1011 try: 

1012 # This is the utilization split evenly between all CPUs. 

1013 # E.g. a busy loop process on a 2-CPU-cores system at this 

1014 # point is reported as 50% instead of 100%. 

1015 overall_cpus_percent = ((delta_proc / delta_time) * 100) 

1016 except ZeroDivisionError: 

1017 # interval was too low 

1018 return 0.0 

1019 else: 

1020 # Note 1: 

1021 # in order to emulate "top" we multiply the value for the num 

1022 # of CPU cores. This way the busy process will be reported as 

1023 # having 100% (or more) usage. 

1024 # 

1025 # Note 2: 

1026 # taskmgr.exe on Windows differs in that it will show 50% 

1027 # instead. 

1028 # 

1029 # Note 3: 

1030 # a percentage > 100 is legitimate as it can result from a 

1031 # process with multiple threads running on different CPU 

1032 # cores (top does the same), see: 

1033 # http://stackoverflow.com/questions/1032357 

1034 # https://github.com/giampaolo/psutil/issues/474 

1035 single_cpu_percent = overall_cpus_percent * num_cpus 

1036 return round(single_cpu_percent, 1) 

1037 

1038 @memoize_when_activated 

1039 def cpu_times(self): 

1040 """Return a (user, system, children_user, children_system) 

1041 namedtuple representing the accumulated process time, in 

1042 seconds. 

1043 This is similar to os.times() but per-process. 

1044 On macOS and Windows children_user and children_system are 

1045 always set to 0. 

1046 """ 

1047 return self._proc.cpu_times() 

1048 

1049 @memoize_when_activated 

1050 def memory_info(self): 

1051 """Return a namedtuple with variable fields depending on the 

1052 platform, representing memory information about the process. 

1053 

1054 The "portable" fields available on all platforms are `rss` and `vms`. 

1055 

1056 All numbers are expressed in bytes. 

1057 """ 

1058 return self._proc.memory_info() 

1059 

1060 @_common.deprecated_method(replacement="memory_info") 

1061 def memory_info_ex(self): 

1062 return self.memory_info() 

1063 

1064 def memory_full_info(self): 

1065 """This method returns the same information as memory_info(), 

1066 plus, on some platform (Linux, macOS, Windows), also provides 

1067 additional metrics (USS, PSS and swap). 

1068 The additional metrics provide a better representation of actual 

1069 process memory usage. 

1070 

1071 Namely USS is the memory which is unique to a process and which 

1072 would be freed if the process was terminated right now. 

1073 

1074 It does so by passing through the whole process address. 

1075 As such it usually requires higher user privileges than 

1076 memory_info() and is considerably slower. 

1077 """ 

1078 return self._proc.memory_full_info() 

1079 

1080 def memory_percent(self, memtype="rss"): 

1081 """Compare process memory to total physical system memory and 

1082 calculate process memory utilization as a percentage. 

1083 *memtype* argument is a string that dictates what type of 

1084 process memory you want to compare against (defaults to "rss"). 

1085 The list of available strings can be obtained like this: 

1086 

1087 >>> psutil.Process().memory_info()._fields 

1088 ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss') 

1089 """ 

1090 valid_types = list(_psplatform.pfullmem._fields) 

1091 if memtype not in valid_types: 

1092 raise ValueError("invalid memtype %r; valid types are %r" % ( 

1093 memtype, tuple(valid_types))) 

1094 fun = self.memory_info if memtype in _psplatform.pmem._fields else \ 

1095 self.memory_full_info 

1096 metrics = fun() 

1097 value = getattr(metrics, memtype) 

1098 

1099 # use cached value if available 

1100 total_phymem = _TOTAL_PHYMEM or virtual_memory().total 

1101 if not total_phymem > 0: 

1102 # we should never get here 

1103 raise ValueError( 

1104 "can't calculate process memory percent because " 

1105 "total physical system memory is not positive (%r)" 

1106 % total_phymem) 

1107 return (value / float(total_phymem)) * 100 

1108 

1109 if hasattr(_psplatform.Process, "memory_maps"): 

1110 def memory_maps(self, grouped=True): 

1111 """Return process' mapped memory regions as a list of namedtuples 

1112 whose fields are variable depending on the platform. 

1113 

1114 If *grouped* is True the mapped regions with the same 'path' 

1115 are grouped together and the different memory fields are summed. 

1116 

1117 If *grouped* is False every mapped region is shown as a single 

1118 entity and the namedtuple will also include the mapped region's 

1119 address space ('addr') and permission set ('perms'). 

1120 """ 

1121 it = self._proc.memory_maps() 

1122 if grouped: 

1123 d = {} 

1124 for tupl in it: 

1125 path = tupl[2] 

1126 nums = tupl[3:] 

1127 try: 

1128 d[path] = map(lambda x, y: x + y, d[path], nums) 

1129 except KeyError: 

1130 d[path] = nums 

1131 nt = _psplatform.pmmap_grouped 

1132 return [nt(path, *d[path]) for path in d] # NOQA 

1133 else: 

1134 nt = _psplatform.pmmap_ext 

1135 return [nt(*x) for x in it] 

1136 

1137 def open_files(self): 

1138 """Return files opened by process as a list of 

1139 (path, fd) namedtuples including the absolute file name 

1140 and file descriptor number. 

1141 """ 

1142 return self._proc.open_files() 

1143 

1144 def connections(self, kind='inet'): 

1145 """Return socket connections opened by process as a list of 

1146 (fd, family, type, laddr, raddr, status) namedtuples. 

1147 The *kind* parameter filters for connections that match the 

1148 following criteria: 

1149 

1150 +------------+----------------------------------------------------+ 

1151 | Kind Value | Connections using | 

1152 +------------+----------------------------------------------------+ 

1153 | inet | IPv4 and IPv6 | 

1154 | inet4 | IPv4 | 

1155 | inet6 | IPv6 | 

1156 | tcp | TCP | 

1157 | tcp4 | TCP over IPv4 | 

1158 | tcp6 | TCP over IPv6 | 

1159 | udp | UDP | 

1160 | udp4 | UDP over IPv4 | 

1161 | udp6 | UDP over IPv6 | 

1162 | unix | UNIX socket (both UDP and TCP protocols) | 

1163 | all | the sum of all the possible families and protocols | 

1164 +------------+----------------------------------------------------+ 

1165 """ 

1166 return self._proc.connections(kind) 

1167 

1168 # --- signals 

1169 

1170 if POSIX: 

1171 def _send_signal(self, sig): 

1172 assert not self.pid < 0, self.pid 

1173 if self.pid == 0: 

1174 # see "man 2 kill" 

1175 raise ValueError( 

1176 "preventing sending signal to process with PID 0 as it " 

1177 "would affect every process in the process group of the " 

1178 "calling process (os.getpid()) instead of PID 0") 

1179 try: 

1180 os.kill(self.pid, sig) 

1181 except ProcessLookupError: 

1182 if OPENBSD and pid_exists(self.pid): 

1183 # We do this because os.kill() lies in case of 

1184 # zombie processes. 

1185 raise ZombieProcess(self.pid, self._name, self._ppid) 

1186 else: 

1187 self._gone = True 

1188 raise NoSuchProcess(self.pid, self._name) 

1189 except PermissionError: 

1190 raise AccessDenied(self.pid, self._name) 

1191 

1192 @_assert_pid_not_reused 

1193 def send_signal(self, sig): 

1194 """Send a signal *sig* to process pre-emptively checking 

1195 whether PID has been reused (see signal module constants) . 

1196 On Windows only SIGTERM is valid and is treated as an alias 

1197 for kill(). 

1198 """ 

1199 if POSIX: 

1200 self._send_signal(sig) 

1201 else: # pragma: no cover 

1202 self._proc.send_signal(sig) 

1203 

1204 @_assert_pid_not_reused 

1205 def suspend(self): 

1206 """Suspend process execution with SIGSTOP pre-emptively checking 

1207 whether PID has been reused. 

1208 On Windows this has the effect of suspending all process threads. 

1209 """ 

1210 if POSIX: 

1211 self._send_signal(signal.SIGSTOP) 

1212 else: # pragma: no cover 

1213 self._proc.suspend() 

1214 

1215 @_assert_pid_not_reused 

1216 def resume(self): 

1217 """Resume process execution with SIGCONT pre-emptively checking 

1218 whether PID has been reused. 

1219 On Windows this has the effect of resuming all process threads. 

1220 """ 

1221 if POSIX: 

1222 self._send_signal(signal.SIGCONT) 

1223 else: # pragma: no cover 

1224 self._proc.resume() 

1225 

1226 @_assert_pid_not_reused 

1227 def terminate(self): 

1228 """Terminate the process with SIGTERM pre-emptively checking 

1229 whether PID has been reused. 

1230 On Windows this is an alias for kill(). 

1231 """ 

1232 if POSIX: 

1233 self._send_signal(signal.SIGTERM) 

1234 else: # pragma: no cover 

1235 self._proc.kill() 

1236 

1237 @_assert_pid_not_reused 

1238 def kill(self): 

1239 """Kill the current process with SIGKILL pre-emptively checking 

1240 whether PID has been reused. 

1241 """ 

1242 if POSIX: 

1243 self._send_signal(signal.SIGKILL) 

1244 else: # pragma: no cover 

1245 self._proc.kill() 

1246 

1247 def wait(self, timeout=None): 

1248 """Wait for process to terminate and, if process is a children 

1249 of os.getpid(), also return its exit code, else None. 

1250 On Windows there's no such limitation (exit code is always 

1251 returned). 

1252 

1253 If the process is already terminated immediately return None 

1254 instead of raising NoSuchProcess. 

1255 

1256 If *timeout* (in seconds) is specified and process is still 

1257 alive raise TimeoutExpired. 

1258 

1259 To wait for multiple Process(es) use psutil.wait_procs(). 

1260 """ 

1261 if timeout is not None and not timeout >= 0: 

1262 raise ValueError("timeout must be a positive integer") 

1263 if self._exitcode is not _SENTINEL: 

1264 return self._exitcode 

1265 self._exitcode = self._proc.wait(timeout) 

1266 return self._exitcode 

1267 

1268 

1269# The valid attr names which can be processed by Process.as_dict(). 

1270_as_dict_attrnames = set( 

1271 [x for x in dir(Process) if not x.startswith('_') and x not in 

1272 ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', 

1273 'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit', 

1274 'memory_info_ex', 'oneshot']]) 

1275 

1276 

1277# ===================================================================== 

1278# --- Popen class 

1279# ===================================================================== 

1280 

1281 

1282class Popen(Process): 

1283 """Same as subprocess.Popen, but in addition it provides all 

1284 psutil.Process methods in a single class. 

1285 For the following methods which are common to both classes, psutil 

1286 implementation takes precedence: 

1287 

1288 * send_signal() 

1289 * terminate() 

1290 * kill() 

1291 

1292 This is done in order to avoid killing another process in case its 

1293 PID has been reused, fixing BPO-6973. 

1294 

1295 >>> import psutil 

1296 >>> from subprocess import PIPE 

1297 >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) 

1298 >>> p.name() 

1299 'python' 

1300 >>> p.uids() 

1301 user(real=1000, effective=1000, saved=1000) 

1302 >>> p.username() 

1303 'giampaolo' 

1304 >>> p.communicate() 

1305 ('hi\n', None) 

1306 >>> p.terminate() 

1307 >>> p.wait(timeout=2) 

1308 0 

1309 >>> 

1310 """ 

1311 

1312 def __init__(self, *args, **kwargs): 

1313 # Explicitly avoid to raise NoSuchProcess in case the process 

1314 # spawned by subprocess.Popen terminates too quickly, see: 

1315 # https://github.com/giampaolo/psutil/issues/193 

1316 self.__subproc = subprocess.Popen(*args, **kwargs) 

1317 self._init(self.__subproc.pid, _ignore_nsp=True) 

1318 

1319 def __dir__(self): 

1320 return sorted(set(dir(Popen) + dir(subprocess.Popen))) 

1321 

1322 def __enter__(self): 

1323 if hasattr(self.__subproc, '__enter__'): 

1324 self.__subproc.__enter__() 

1325 return self 

1326 

1327 def __exit__(self, *args, **kwargs): 

1328 if hasattr(self.__subproc, '__exit__'): 

1329 return self.__subproc.__exit__(*args, **kwargs) 

1330 else: 

1331 if self.stdout: 

1332 self.stdout.close() 

1333 if self.stderr: 

1334 self.stderr.close() 

1335 try: 

1336 # Flushing a BufferedWriter may raise an error. 

1337 if self.stdin: 

1338 self.stdin.close() 

1339 finally: 

1340 # Wait for the process to terminate, to avoid zombies. 

1341 self.wait() 

1342 

1343 def __getattribute__(self, name): 

1344 try: 

1345 return object.__getattribute__(self, name) 

1346 except AttributeError: 

1347 try: 

1348 return object.__getattribute__(self.__subproc, name) 

1349 except AttributeError: 

1350 raise AttributeError("%s instance has no attribute '%s'" 

1351 % (self.__class__.__name__, name)) 

1352 

1353 def wait(self, timeout=None): 

1354 if self.__subproc.returncode is not None: 

1355 return self.__subproc.returncode 

1356 ret = super(Popen, self).wait(timeout) 

1357 self.__subproc.returncode = ret 

1358 return ret 

1359 

1360 

1361# ===================================================================== 

1362# --- system processes related functions 

1363# ===================================================================== 

1364 

1365 

1366def pids(): 

1367 """Return a list of current running PIDs.""" 

1368 global _LOWEST_PID 

1369 ret = sorted(_psplatform.pids()) 

1370 _LOWEST_PID = ret[0] 

1371 return ret 

1372 

1373 

1374def pid_exists(pid): 

1375 """Return True if given PID exists in the current process list. 

1376 This is faster than doing "pid in psutil.pids()" and 

1377 should be preferred. 

1378 """ 

1379 if pid < 0: 

1380 return False 

1381 elif pid == 0 and POSIX: 

1382 # On POSIX we use os.kill() to determine PID existence. 

1383 # According to "man 2 kill" PID 0 has a special meaning 

1384 # though: it refers to <<every process in the process 

1385 # group of the calling process>> and that is not we want 

1386 # to do here. 

1387 return pid in pids() 

1388 else: 

1389 return _psplatform.pid_exists(pid) 

1390 

1391 

1392_pmap = {} 

1393 

1394 

1395def process_iter(attrs=None, ad_value=None): 

1396 """Return a generator yielding a Process instance for all 

1397 running processes. 

1398 

1399 Every new Process instance is only created once and then cached 

1400 into an internal table which is updated every time this is used. 

1401 

1402 Cached Process instances are checked for identity so that you're 

1403 safe in case a PID has been reused by another process, in which 

1404 case the cached instance is updated. 

1405 

1406 The sorting order in which processes are yielded is based on 

1407 their PIDs. 

1408 

1409 *attrs* and *ad_value* have the same meaning as in 

1410 Process.as_dict(). If *attrs* is specified as_dict() is called 

1411 and the resulting dict is stored as a 'info' attribute attached 

1412 to returned Process instance. 

1413 If *attrs* is an empty list it will retrieve all process info 

1414 (slow). 

1415 """ 

1416 global _pmap 

1417 

1418 def add(pid): 

1419 proc = Process(pid) 

1420 if attrs is not None: 

1421 proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) 

1422 pmap[proc.pid] = proc 

1423 return proc 

1424 

1425 def remove(pid): 

1426 pmap.pop(pid, None) 

1427 

1428 pmap = _pmap.copy() 

1429 a = set(pids()) 

1430 b = set(pmap.keys()) 

1431 new_pids = a - b 

1432 gone_pids = b - a 

1433 for pid in gone_pids: 

1434 remove(pid) 

1435 try: 

1436 ls = sorted(list(pmap.items()) + list(dict.fromkeys(new_pids).items())) 

1437 for pid, proc in ls: 

1438 try: 

1439 if proc is None: # new process 

1440 yield add(pid) 

1441 else: 

1442 # use is_running() to check whether PID has been 

1443 # reused by another process in which case yield a 

1444 # new Process instance 

1445 if proc.is_running(): 

1446 if attrs is not None: 

1447 proc.info = proc.as_dict( 

1448 attrs=attrs, ad_value=ad_value) 

1449 yield proc 

1450 else: 

1451 yield add(pid) 

1452 except NoSuchProcess: 

1453 remove(pid) 

1454 except AccessDenied: 

1455 # Process creation time can't be determined hence there's 

1456 # no way to tell whether the pid of the cached process 

1457 # has been reused. Just return the cached version. 

1458 if proc is None and pid in pmap: 

1459 try: 

1460 yield pmap[pid] 

1461 except KeyError: 

1462 # If we get here it is likely that 2 threads were 

1463 # using process_iter(). 

1464 pass 

1465 else: 

1466 raise 

1467 finally: 

1468 _pmap = pmap 

1469 

1470 

1471def wait_procs(procs, timeout=None, callback=None): 

1472 """Convenience function which waits for a list of processes to 

1473 terminate. 

1474 

1475 Return a (gone, alive) tuple indicating which processes 

1476 are gone and which ones are still alive. 

1477 

1478 The gone ones will have a new *returncode* attribute indicating 

1479 process exit status (may be None). 

1480 

1481 *callback* is a function which gets called every time a process 

1482 terminates (a Process instance is passed as callback argument). 

1483 

1484 Function will return as soon as all processes terminate or when 

1485 *timeout* occurs. 

1486 Differently from Process.wait() it will not raise TimeoutExpired if 

1487 *timeout* occurs. 

1488 

1489 Typical use case is: 

1490 

1491 - send SIGTERM to a list of processes 

1492 - give them some time to terminate 

1493 - send SIGKILL to those ones which are still alive 

1494 

1495 Example: 

1496 

1497 >>> def on_terminate(proc): 

1498 ... print("process {} terminated".format(proc)) 

1499 ... 

1500 >>> for p in procs: 

1501 ... p.terminate() 

1502 ... 

1503 >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) 

1504 >>> for p in alive: 

1505 ... p.kill() 

1506 """ 

1507 def check_gone(proc, timeout): 

1508 try: 

1509 returncode = proc.wait(timeout=timeout) 

1510 except TimeoutExpired: 

1511 pass 

1512 except _SubprocessTimeoutExpired: 

1513 pass 

1514 else: 

1515 if returncode is not None or not proc.is_running(): 

1516 # Set new Process instance attribute. 

1517 proc.returncode = returncode 

1518 gone.add(proc) 

1519 if callback is not None: 

1520 callback(proc) 

1521 

1522 if timeout is not None and not timeout >= 0: 

1523 msg = "timeout must be a positive integer, got %s" % timeout 

1524 raise ValueError(msg) 

1525 gone = set() 

1526 alive = set(procs) 

1527 if callback is not None and not callable(callback): 

1528 raise TypeError("callback %r is not a callable" % callable) 

1529 if timeout is not None: 

1530 deadline = _timer() + timeout 

1531 

1532 while alive: 

1533 if timeout is not None and timeout <= 0: 

1534 break 

1535 for proc in alive: 

1536 # Make sure that every complete iteration (all processes) 

1537 # will last max 1 sec. 

1538 # We do this because we don't want to wait too long on a 

1539 # single process: in case it terminates too late other 

1540 # processes may disappear in the meantime and their PID 

1541 # reused. 

1542 max_timeout = 1.0 / len(alive) 

1543 if timeout is not None: 

1544 timeout = min((deadline - _timer()), max_timeout) 

1545 if timeout <= 0: 

1546 break 

1547 check_gone(proc, timeout) 

1548 else: 

1549 check_gone(proc, max_timeout) 

1550 alive = alive - gone 

1551 

1552 if alive: 

1553 # Last attempt over processes survived so far. 

1554 # timeout == 0 won't make this function wait any further. 

1555 for proc in alive: 

1556 check_gone(proc, 0) 

1557 alive = alive - gone 

1558 

1559 return (list(gone), list(alive)) 

1560 

1561 

1562# ===================================================================== 

1563# --- CPU related functions 

1564# ===================================================================== 

1565 

1566 

1567def cpu_count(logical=True): 

1568 """Return the number of logical CPUs in the system (same as 

1569 os.cpu_count() in Python 3.4). 

1570 

1571 If *logical* is False return the number of physical cores only 

1572 (e.g. hyper thread CPUs are excluded). 

1573 

1574 Return None if undetermined. 

1575 

1576 The return value is cached after first call. 

1577 If desired cache can be cleared like this: 

1578 

1579 >>> psutil.cpu_count.cache_clear() 

1580 """ 

1581 if logical: 

1582 ret = _psplatform.cpu_count_logical() 

1583 else: 

1584 ret = _psplatform.cpu_count_cores() 

1585 if ret is not None and ret < 1: 

1586 ret = None 

1587 return ret 

1588 

1589 

1590def cpu_times(percpu=False): 

1591 """Return system-wide CPU times as a namedtuple. 

1592 Every CPU time represents the seconds the CPU has spent in the 

1593 given mode. The namedtuple's fields availability varies depending on the 

1594 platform: 

1595 

1596 - user 

1597 - system 

1598 - idle 

1599 - nice (UNIX) 

1600 - iowait (Linux) 

1601 - irq (Linux, FreeBSD) 

1602 - softirq (Linux) 

1603 - steal (Linux >= 2.6.11) 

1604 - guest (Linux >= 2.6.24) 

1605 - guest_nice (Linux >= 3.2.0) 

1606 

1607 When *percpu* is True return a list of namedtuples for each CPU. 

1608 First element of the list refers to first CPU, second element 

1609 to second CPU and so on. 

1610 The order of the list is consistent across calls. 

1611 """ 

1612 if not percpu: 

1613 return _psplatform.cpu_times() 

1614 else: 

1615 return _psplatform.per_cpu_times() 

1616 

1617 

1618try: 

1619 _last_cpu_times = cpu_times() 

1620except Exception: 

1621 # Don't want to crash at import time. 

1622 _last_cpu_times = None 

1623 

1624try: 

1625 _last_per_cpu_times = cpu_times(percpu=True) 

1626except Exception: 

1627 # Don't want to crash at import time. 

1628 _last_per_cpu_times = None 

1629 

1630 

1631def _cpu_tot_time(times): 

1632 """Given a cpu_time() ntuple calculates the total CPU time 

1633 (including idle time). 

1634 """ 

1635 tot = sum(times) 

1636 if LINUX: 

1637 # On Linux guest times are already accounted in "user" or 

1638 # "nice" times, so we subtract them from total. 

1639 # Htop does the same. References: 

1640 # https://github.com/giampaolo/psutil/pull/940 

1641 # http://unix.stackexchange.com/questions/178045 

1642 # https://github.com/torvalds/linux/blob/ 

1643 # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/ 

1644 # cputime.c#L158 

1645 tot -= getattr(times, "guest", 0) # Linux 2.6.24+ 

1646 tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+ 

1647 return tot 

1648 

1649 

1650def _cpu_busy_time(times): 

1651 """Given a cpu_time() ntuple calculates the busy CPU time. 

1652 We do so by subtracting all idle CPU times. 

1653 """ 

1654 busy = _cpu_tot_time(times) 

1655 busy -= times.idle 

1656 # Linux: "iowait" is time during which the CPU does not do anything 

1657 # (waits for IO to complete). On Linux IO wait is *not* accounted 

1658 # in "idle" time so we subtract it. Htop does the same. 

1659 # References: 

1660 # https://github.com/torvalds/linux/blob/ 

1661 # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244 

1662 busy -= getattr(times, "iowait", 0) 

1663 return busy 

1664 

1665 

1666def _cpu_times_deltas(t1, t2): 

1667 assert t1._fields == t2._fields, (t1, t2) 

1668 field_deltas = [] 

1669 for field in _psplatform.scputimes._fields: 

1670 field_delta = getattr(t2, field) - getattr(t1, field) 

1671 # CPU times are always supposed to increase over time 

1672 # or at least remain the same and that's because time 

1673 # cannot go backwards. 

1674 # Surprisingly sometimes this might not be the case (at 

1675 # least on Windows and Linux), see: 

1676 # https://github.com/giampaolo/psutil/issues/392 

1677 # https://github.com/giampaolo/psutil/issues/645 

1678 # https://github.com/giampaolo/psutil/issues/1210 

1679 # Trim negative deltas to zero to ignore decreasing fields. 

1680 # top does the same. Reference: 

1681 # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063 

1682 field_delta = max(0, field_delta) 

1683 field_deltas.append(field_delta) 

1684 return _psplatform.scputimes(*field_deltas) 

1685 

1686 

1687def cpu_percent(interval=None, percpu=False): 

1688 """Return a float representing the current system-wide CPU 

1689 utilization as a percentage. 

1690 

1691 When *interval* is > 0.0 compares system CPU times elapsed before 

1692 and after the interval (blocking). 

1693 

1694 When *interval* is 0.0 or None compares system CPU times elapsed 

1695 since last call or module import, returning immediately (non 

1696 blocking). That means the first time this is called it will 

1697 return a meaningless 0.0 value which you should ignore. 

1698 In this case is recommended for accuracy that this function be 

1699 called with at least 0.1 seconds between calls. 

1700 

1701 When *percpu* is True returns a list of floats representing the 

1702 utilization as a percentage for each CPU. 

1703 First element of the list refers to first CPU, second element 

1704 to second CPU and so on. 

1705 The order of the list is consistent across calls. 

1706 

1707 Examples: 

1708 

1709 >>> # blocking, system-wide 

1710 >>> psutil.cpu_percent(interval=1) 

1711 2.0 

1712 >>> 

1713 >>> # blocking, per-cpu 

1714 >>> psutil.cpu_percent(interval=1, percpu=True) 

1715 [2.0, 1.0] 

1716 >>> 

1717 >>> # non-blocking (percentage since last call) 

1718 >>> psutil.cpu_percent(interval=None) 

1719 2.9 

1720 >>> 

1721 """ 

1722 global _last_cpu_times 

1723 global _last_per_cpu_times 

1724 blocking = interval is not None and interval > 0.0 

1725 if interval is not None and interval < 0: 

1726 raise ValueError("interval is not positive (got %r)" % interval) 

1727 

1728 def calculate(t1, t2): 

1729 times_delta = _cpu_times_deltas(t1, t2) 

1730 all_delta = _cpu_tot_time(times_delta) 

1731 busy_delta = _cpu_busy_time(times_delta) 

1732 

1733 try: 

1734 busy_perc = (busy_delta / all_delta) * 100 

1735 except ZeroDivisionError: 

1736 return 0.0 

1737 else: 

1738 return round(busy_perc, 1) 

1739 

1740 # system-wide usage 

1741 if not percpu: 

1742 if blocking: 

1743 t1 = cpu_times() 

1744 time.sleep(interval) 

1745 else: 

1746 t1 = _last_cpu_times 

1747 if t1 is None: 

1748 # Something bad happened at import time. We'll 

1749 # get a meaningful result on the next call. See: 

1750 # https://github.com/giampaolo/psutil/pull/715 

1751 t1 = cpu_times() 

1752 _last_cpu_times = cpu_times() 

1753 return calculate(t1, _last_cpu_times) 

1754 # per-cpu usage 

1755 else: 

1756 ret = [] 

1757 if blocking: 

1758 tot1 = cpu_times(percpu=True) 

1759 time.sleep(interval) 

1760 else: 

1761 tot1 = _last_per_cpu_times 

1762 if tot1 is None: 

1763 # Something bad happened at import time. We'll 

1764 # get a meaningful result on the next call. See: 

1765 # https://github.com/giampaolo/psutil/pull/715 

1766 tot1 = cpu_times(percpu=True) 

1767 _last_per_cpu_times = cpu_times(percpu=True) 

1768 for t1, t2 in zip(tot1, _last_per_cpu_times): 

1769 ret.append(calculate(t1, t2)) 

1770 return ret 

1771 

1772 

1773# Use separate global vars for cpu_times_percent() so that it's 

1774# independent from cpu_percent() and they can both be used within 

1775# the same program. 

1776_last_cpu_times_2 = _last_cpu_times 

1777_last_per_cpu_times_2 = _last_per_cpu_times 

1778 

1779 

1780def cpu_times_percent(interval=None, percpu=False): 

1781 """Same as cpu_percent() but provides utilization percentages 

1782 for each specific CPU time as is returned by cpu_times(). 

1783 For instance, on Linux we'll get: 

1784 

1785 >>> cpu_times_percent() 

1786 cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, 

1787 irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) 

1788 >>> 

1789 

1790 *interval* and *percpu* arguments have the same meaning as in 

1791 cpu_percent(). 

1792 """ 

1793 global _last_cpu_times_2 

1794 global _last_per_cpu_times_2 

1795 blocking = interval is not None and interval > 0.0 

1796 if interval is not None and interval < 0: 

1797 raise ValueError("interval is not positive (got %r)" % interval) 

1798 

1799 def calculate(t1, t2): 

1800 nums = [] 

1801 times_delta = _cpu_times_deltas(t1, t2) 

1802 all_delta = _cpu_tot_time(times_delta) 

1803 # "scale" is the value to multiply each delta with to get percentages. 

1804 # We use "max" to avoid division by zero (if all_delta is 0, then all 

1805 # fields are 0 so percentages will be 0 too. all_delta cannot be a 

1806 # fraction because cpu times are integers) 

1807 scale = 100.0 / max(1, all_delta) 

1808 for field_delta in times_delta: 

1809 field_perc = field_delta * scale 

1810 field_perc = round(field_perc, 1) 

1811 # make sure we don't return negative values or values over 100% 

1812 field_perc = min(max(0.0, field_perc), 100.0) 

1813 nums.append(field_perc) 

1814 return _psplatform.scputimes(*nums) 

1815 

1816 # system-wide usage 

1817 if not percpu: 

1818 if blocking: 

1819 t1 = cpu_times() 

1820 time.sleep(interval) 

1821 else: 

1822 t1 = _last_cpu_times_2 

1823 if t1 is None: 

1824 # Something bad happened at import time. We'll 

1825 # get a meaningful result on the next call. See: 

1826 # https://github.com/giampaolo/psutil/pull/715 

1827 t1 = cpu_times() 

1828 _last_cpu_times_2 = cpu_times() 

1829 return calculate(t1, _last_cpu_times_2) 

1830 # per-cpu usage 

1831 else: 

1832 ret = [] 

1833 if blocking: 

1834 tot1 = cpu_times(percpu=True) 

1835 time.sleep(interval) 

1836 else: 

1837 tot1 = _last_per_cpu_times_2 

1838 if tot1 is None: 

1839 # Something bad happened at import time. We'll 

1840 # get a meaningful result on the next call. See: 

1841 # https://github.com/giampaolo/psutil/pull/715 

1842 tot1 = cpu_times(percpu=True) 

1843 _last_per_cpu_times_2 = cpu_times(percpu=True) 

1844 for t1, t2 in zip(tot1, _last_per_cpu_times_2): 

1845 ret.append(calculate(t1, t2)) 

1846 return ret 

1847 

1848 

1849def cpu_stats(): 

1850 """Return CPU statistics.""" 

1851 return _psplatform.cpu_stats() 

1852 

1853 

1854if hasattr(_psplatform, "cpu_freq"): 

1855 

1856 def cpu_freq(percpu=False): 

1857 """Return CPU frequency as a namedtuple including current, 

1858 min and max frequency expressed in Mhz. 

1859 

1860 If *percpu* is True and the system supports per-cpu frequency 

1861 retrieval (Linux only) a list of frequencies is returned for 

1862 each CPU. If not a list with one element is returned. 

1863 """ 

1864 ret = _psplatform.cpu_freq() 

1865 if percpu: 

1866 return ret 

1867 else: 

1868 num_cpus = float(len(ret)) 

1869 if num_cpus == 0: 

1870 return None 

1871 elif num_cpus == 1: 

1872 return ret[0] 

1873 else: 

1874 currs, mins, maxs = 0.0, 0.0, 0.0 

1875 set_none = False 

1876 for cpu in ret: 

1877 currs += cpu.current 

1878 # On Linux if /proc/cpuinfo is used min/max are set 

1879 # to None. 

1880 if LINUX and cpu.min is None: 

1881 set_none = True 

1882 continue 

1883 mins += cpu.min 

1884 maxs += cpu.max 

1885 

1886 current = currs / num_cpus 

1887 

1888 if set_none: 

1889 min_ = max_ = None 

1890 else: 

1891 min_ = mins / num_cpus 

1892 max_ = maxs / num_cpus 

1893 

1894 return _common.scpufreq(current, min_, max_) 

1895 

1896 __all__.append("cpu_freq") 

1897 

1898 

1899if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"): 

1900 # Perform this hasattr check once on import time to either use the 

1901 # platform based code or proxy straight from the os module. 

1902 if hasattr(os, "getloadavg"): 

1903 getloadavg = os.getloadavg 

1904 else: 

1905 getloadavg = _psplatform.getloadavg 

1906 

1907 __all__.append("getloadavg") 

1908 

1909 

1910# ===================================================================== 

1911# --- system memory related functions 

1912# ===================================================================== 

1913 

1914 

1915def virtual_memory(): 

1916 """Return statistics about system memory usage as a namedtuple 

1917 including the following fields, expressed in bytes: 

1918 

1919 - total: 

1920 total physical memory available. 

1921 

1922 - available: 

1923 the memory that can be given instantly to processes without the 

1924 system going into swap. 

1925 This is calculated by summing different memory values depending 

1926 on the platform and it is supposed to be used to monitor actual 

1927 memory usage in a cross platform fashion. 

1928 

1929 - percent: 

1930 the percentage usage calculated as (total - available) / total * 100 

1931 

1932 - used: 

1933 memory used, calculated differently depending on the platform and 

1934 designed for informational purposes only: 

1935 macOS: active + wired 

1936 BSD: active + wired + cached 

1937 Linux: total - free 

1938 

1939 - free: 

1940 memory not being used at all (zeroed) that is readily available; 

1941 note that this doesn't reflect the actual memory available 

1942 (use 'available' instead) 

1943 

1944 Platform-specific fields: 

1945 

1946 - active (UNIX): 

1947 memory currently in use or very recently used, and so it is in RAM. 

1948 

1949 - inactive (UNIX): 

1950 memory that is marked as not used. 

1951 

1952 - buffers (BSD, Linux): 

1953 cache for things like file system metadata. 

1954 

1955 - cached (BSD, macOS): 

1956 cache for various things. 

1957 

1958 - wired (macOS, BSD): 

1959 memory that is marked to always stay in RAM. It is never moved to disk. 

1960 

1961 - shared (BSD): 

1962 memory that may be simultaneously accessed by multiple processes. 

1963 

1964 The sum of 'used' and 'available' does not necessarily equal total. 

1965 On Windows 'available' and 'free' are the same. 

1966 """ 

1967 global _TOTAL_PHYMEM 

1968 ret = _psplatform.virtual_memory() 

1969 # cached for later use in Process.memory_percent() 

1970 _TOTAL_PHYMEM = ret.total 

1971 return ret 

1972 

1973 

1974def swap_memory(): 

1975 """Return system swap memory statistics as a namedtuple including 

1976 the following fields: 

1977 

1978 - total: total swap memory in bytes 

1979 - used: used swap memory in bytes 

1980 - free: free swap memory in bytes 

1981 - percent: the percentage usage 

1982 - sin: no. of bytes the system has swapped in from disk (cumulative) 

1983 - sout: no. of bytes the system has swapped out from disk (cumulative) 

1984 

1985 'sin' and 'sout' on Windows are meaningless and always set to 0. 

1986 """ 

1987 return _psplatform.swap_memory() 

1988 

1989 

1990# ===================================================================== 

1991# --- disks/paritions related functions 

1992# ===================================================================== 

1993 

1994 

1995def disk_usage(path): 

1996 """Return disk usage statistics about the given *path* as a 

1997 namedtuple including total, used and free space expressed in bytes 

1998 plus the percentage usage. 

1999 """ 

2000 return _psplatform.disk_usage(path) 

2001 

2002 

2003def disk_partitions(all=False): 

2004 """Return mounted partitions as a list of 

2005 (device, mountpoint, fstype, opts) namedtuple. 

2006 'opts' field is a raw string separated by commas indicating mount 

2007 options which may vary depending on the platform. 

2008 

2009 If *all* parameter is False return physical devices only and ignore 

2010 all others. 

2011 """ 

2012 def pathconf(path, name): 

2013 try: 

2014 return os.pathconf(path, name) 

2015 except (OSError, AttributeError): 

2016 pass 

2017 

2018 ret = _psplatform.disk_partitions(all) 

2019 if POSIX: 

2020 new = [] 

2021 for item in ret: 

2022 nt = item._replace( 

2023 maxfile=pathconf(item.mountpoint, 'PC_NAME_MAX'), 

2024 maxpath=pathconf(item.mountpoint, 'PC_PATH_MAX')) 

2025 new.append(nt) 

2026 return new 

2027 else: 

2028 return ret 

2029 

2030 

2031def disk_io_counters(perdisk=False, nowrap=True): 

2032 """Return system disk I/O statistics as a namedtuple including 

2033 the following fields: 

2034 

2035 - read_count: number of reads 

2036 - write_count: number of writes 

2037 - read_bytes: number of bytes read 

2038 - write_bytes: number of bytes written 

2039 - read_time: time spent reading from disk (in ms) 

2040 - write_time: time spent writing to disk (in ms) 

2041 

2042 Platform specific: 

2043 

2044 - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms) 

2045 - read_merged_count (Linux): number of merged reads 

2046 - write_merged_count (Linux): number of merged writes 

2047 

2048 If *perdisk* is True return the same information for every 

2049 physical disk installed on the system as a dictionary 

2050 with partition names as the keys and the namedtuple 

2051 described above as the values. 

2052 

2053 If *nowrap* is True it detects and adjust the numbers which overflow 

2054 and wrap (restart from 0) and add "old value" to "new value" so that 

2055 the returned numbers will always be increasing or remain the same, 

2056 but never decrease. 

2057 "disk_io_counters.cache_clear()" can be used to invalidate the 

2058 cache. 

2059 

2060 On recent Windows versions 'diskperf -y' command may need to be 

2061 executed first otherwise this function won't find any disk. 

2062 """ 

2063 kwargs = dict(perdisk=perdisk) if LINUX else {} 

2064 rawdict = _psplatform.disk_io_counters(**kwargs) 

2065 if not rawdict: 

2066 return {} if perdisk else None 

2067 if nowrap: 

2068 rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters') 

2069 nt = getattr(_psplatform, "sdiskio", _common.sdiskio) 

2070 if perdisk: 

2071 for disk, fields in rawdict.items(): 

2072 rawdict[disk] = nt(*fields) 

2073 return rawdict 

2074 else: 

2075 return nt(*(sum(x) for x in zip(*rawdict.values()))) 

2076 

2077 

2078disk_io_counters.cache_clear = functools.partial( 

2079 _wrap_numbers.cache_clear, 'psutil.disk_io_counters') 

2080disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" 

2081 

2082 

2083# ===================================================================== 

2084# --- network related functions 

2085# ===================================================================== 

2086 

2087 

2088def net_io_counters(pernic=False, nowrap=True): 

2089 """Return network I/O statistics as a namedtuple including 

2090 the following fields: 

2091 

2092 - bytes_sent: number of bytes sent 

2093 - bytes_recv: number of bytes received 

2094 - packets_sent: number of packets sent 

2095 - packets_recv: number of packets received 

2096 - errin: total number of errors while receiving 

2097 - errout: total number of errors while sending 

2098 - dropin: total number of incoming packets which were dropped 

2099 - dropout: total number of outgoing packets which were dropped 

2100 (always 0 on macOS and BSD) 

2101 

2102 If *pernic* is True return the same information for every 

2103 network interface installed on the system as a dictionary 

2104 with network interface names as the keys and the namedtuple 

2105 described above as the values. 

2106 

2107 If *nowrap* is True it detects and adjust the numbers which overflow 

2108 and wrap (restart from 0) and add "old value" to "new value" so that 

2109 the returned numbers will always be increasing or remain the same, 

2110 but never decrease. 

2111 "disk_io_counters.cache_clear()" can be used to invalidate the 

2112 cache. 

2113 """ 

2114 rawdict = _psplatform.net_io_counters() 

2115 if not rawdict: 

2116 return {} if pernic else None 

2117 if nowrap: 

2118 rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters') 

2119 if pernic: 

2120 for nic, fields in rawdict.items(): 

2121 rawdict[nic] = _common.snetio(*fields) 

2122 return rawdict 

2123 else: 

2124 return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) 

2125 

2126 

2127net_io_counters.cache_clear = functools.partial( 

2128 _wrap_numbers.cache_clear, 'psutil.net_io_counters') 

2129net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" 

2130 

2131 

2132def net_connections(kind='inet'): 

2133 """Return system-wide socket connections as a list of 

2134 (fd, family, type, laddr, raddr, status, pid) namedtuples. 

2135 In case of limited privileges 'fd' and 'pid' may be set to -1 

2136 and None respectively. 

2137 The *kind* parameter filters for connections that fit the 

2138 following criteria: 

2139 

2140 +------------+----------------------------------------------------+ 

2141 | Kind Value | Connections using | 

2142 +------------+----------------------------------------------------+ 

2143 | inet | IPv4 and IPv6 | 

2144 | inet4 | IPv4 | 

2145 | inet6 | IPv6 | 

2146 | tcp | TCP | 

2147 | tcp4 | TCP over IPv4 | 

2148 | tcp6 | TCP over IPv6 | 

2149 | udp | UDP | 

2150 | udp4 | UDP over IPv4 | 

2151 | udp6 | UDP over IPv6 | 

2152 | unix | UNIX socket (both UDP and TCP protocols) | 

2153 | all | the sum of all the possible families and protocols | 

2154 +------------+----------------------------------------------------+ 

2155 

2156 On macOS this function requires root privileges. 

2157 """ 

2158 return _psplatform.net_connections(kind) 

2159 

2160 

2161def net_if_addrs(): 

2162 """Return the addresses associated to each NIC (network interface 

2163 card) installed on the system as a dictionary whose keys are the 

2164 NIC names and value is a list of namedtuples for each address 

2165 assigned to the NIC. Each namedtuple includes 5 fields: 

2166 

2167 - family: can be either socket.AF_INET, socket.AF_INET6 or 

2168 psutil.AF_LINK, which refers to a MAC address. 

2169 - address: is the primary address and it is always set. 

2170 - netmask: and 'broadcast' and 'ptp' may be None. 

2171 - ptp: stands for "point to point" and references the 

2172 destination address on a point to point interface 

2173 (typically a VPN). 

2174 - broadcast: and *ptp* are mutually exclusive. 

2175 

2176 Note: you can have more than one address of the same family 

2177 associated with each interface. 

2178 """ 

2179 has_enums = sys.version_info >= (3, 4) 

2180 if has_enums: 

2181 import socket 

2182 rawlist = _psplatform.net_if_addrs() 

2183 rawlist.sort(key=lambda x: x[1]) # sort by family 

2184 ret = collections.defaultdict(list) 

2185 for name, fam, addr, mask, broadcast, ptp in rawlist: 

2186 if has_enums: 

2187 try: 

2188 fam = socket.AddressFamily(fam) 

2189 except ValueError: 

2190 if WINDOWS and fam == -1: 

2191 fam = _psplatform.AF_LINK 

2192 elif (hasattr(_psplatform, "AF_LINK") and 

2193 _psplatform.AF_LINK == fam): 

2194 # Linux defines AF_LINK as an alias for AF_PACKET. 

2195 # We re-set the family here so that repr(family) 

2196 # will show AF_LINK rather than AF_PACKET 

2197 fam = _psplatform.AF_LINK 

2198 if fam == _psplatform.AF_LINK: 

2199 # The underlying C function may return an incomplete MAC 

2200 # address in which case we fill it with null bytes, see: 

2201 # https://github.com/giampaolo/psutil/issues/786 

2202 separator = ":" if POSIX else "-" 

2203 while addr.count(separator) < 5: 

2204 addr += "%s00" % separator 

2205 ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp)) 

2206 return dict(ret) 

2207 

2208 

2209def net_if_stats(): 

2210 """Return information about each NIC (network interface card) 

2211 installed on the system as a dictionary whose keys are the 

2212 NIC names and value is a namedtuple with the following fields: 

2213 

2214 - isup: whether the interface is up (bool) 

2215 - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or 

2216 NIC_DUPLEX_UNKNOWN 

2217 - speed: the NIC speed expressed in mega bits (MB); if it can't 

2218 be determined (e.g. 'localhost') it will be set to 0. 

2219 - mtu: the maximum transmission unit expressed in bytes. 

2220 """ 

2221 return _psplatform.net_if_stats() 

2222 

2223 

2224# ===================================================================== 

2225# --- sensors 

2226# ===================================================================== 

2227 

2228 

2229# Linux, macOS 

2230if hasattr(_psplatform, "sensors_temperatures"): 

2231 

2232 def sensors_temperatures(fahrenheit=False): 

2233 """Return hardware temperatures. Each entry is a namedtuple 

2234 representing a certain hardware sensor (it may be a CPU, an 

2235 hard disk or something else, depending on the OS and its 

2236 configuration). 

2237 All temperatures are expressed in celsius unless *fahrenheit* 

2238 is set to True. 

2239 """ 

2240 def convert(n): 

2241 if n is not None: 

2242 return (float(n) * 9 / 5) + 32 if fahrenheit else n 

2243 

2244 ret = collections.defaultdict(list) 

2245 rawdict = _psplatform.sensors_temperatures() 

2246 

2247 for name, values in rawdict.items(): 

2248 while values: 

2249 label, current, high, critical = values.pop(0) 

2250 current = convert(current) 

2251 high = convert(high) 

2252 critical = convert(critical) 

2253 

2254 if high and not critical: 

2255 critical = high 

2256 elif critical and not high: 

2257 high = critical 

2258 

2259 ret[name].append( 

2260 _common.shwtemp(label, current, high, critical)) 

2261 

2262 return dict(ret) 

2263 

2264 __all__.append("sensors_temperatures") 

2265 

2266 

2267# Linux 

2268if hasattr(_psplatform, "sensors_fans"): 

2269 

2270 def sensors_fans(): 

2271 """Return fans speed. Each entry is a namedtuple 

2272 representing a certain hardware sensor. 

2273 All speed are expressed in RPM (rounds per minute). 

2274 """ 

2275 return _psplatform.sensors_fans() 

2276 

2277 __all__.append("sensors_fans") 

2278 

2279 

2280# Linux, Windows, FreeBSD, macOS 

2281if hasattr(_psplatform, "sensors_battery"): 

2282 

2283 def sensors_battery(): 

2284 """Return battery information. If no battery is installed 

2285 returns None. 

2286 

2287 - percent: battery power left as a percentage. 

2288 - secsleft: a rough approximation of how many seconds are left 

2289 before the battery runs out of power. May be 

2290 POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED. 

2291 - power_plugged: True if the AC power cable is connected. 

2292 """ 

2293 return _psplatform.sensors_battery() 

2294 

2295 __all__.append("sensors_battery") 

2296 

2297 

2298# ===================================================================== 

2299# --- other system related functions 

2300# ===================================================================== 

2301 

2302 

2303def boot_time(): 

2304 """Return the system boot time expressed in seconds since the epoch.""" 

2305 # Note: we are not caching this because it is subject to 

2306 # system clock updates. 

2307 return _psplatform.boot_time() 

2308 

2309 

2310def users(): 

2311 """Return users currently connected on the system as a list of 

2312 namedtuples including the following fields. 

2313 

2314 - user: the name of the user 

2315 - terminal: the tty or pseudo-tty associated with the user, if any. 

2316 - host: the host name associated with the entry, if any. 

2317 - started: the creation time as a floating point number expressed in 

2318 seconds since the epoch. 

2319 """ 

2320 return _psplatform.users() 

2321 

2322 

2323# ===================================================================== 

2324# --- Windows services 

2325# ===================================================================== 

2326 

2327 

2328if WINDOWS: 

2329 

2330 def win_service_iter(): 

2331 """Return a generator yielding a WindowsService instance for all 

2332 Windows services installed. 

2333 """ 

2334 return _psplatform.win_service_iter() 

2335 

2336 def win_service_get(name): 

2337 """Get a Windows service by *name*. 

2338 Raise NoSuchProcess if no service with such name exists. 

2339 """ 

2340 return _psplatform.win_service_get(name) 

2341 

2342 

2343# ===================================================================== 

2344 

2345 

2346def _set_debug(value): 

2347 """Enable or disable PSUTIL_DEBUG option, which prints debugging 

2348 messages to stderr. 

2349 """ 

2350 import psutil._common 

2351 psutil._common.PSUTIL_DEBUG = bool(value) 

2352 _psplatform.cext.set_debug(bool(value)) 

2353 

2354 

2355def test(): # pragma: no cover 

2356 from ._common import bytes2human 

2357 from ._compat import get_terminal_size 

2358 

2359 today_day = datetime.date.today() 

2360 templ = "%-10s %5s %5s %7s %7s %5s %6s %6s %6s %s" 

2361 attrs = ['pid', 'memory_percent', 'name', 'cmdline', 'cpu_times', 

2362 'create_time', 'memory_info', 'status', 'nice', 'username'] 

2363 print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "NICE", # NOQA 

2364 "STATUS", "START", "TIME", "CMDLINE")) 

2365 for p in process_iter(attrs, ad_value=None): 

2366 if p.info['create_time']: 

2367 ctime = datetime.datetime.fromtimestamp(p.info['create_time']) 

2368 if ctime.date() == today_day: 

2369 ctime = ctime.strftime("%H:%M") 

2370 else: 

2371 ctime = ctime.strftime("%b%d") 

2372 else: 

2373 ctime = '' 

2374 if p.info['cpu_times']: 

2375 cputime = time.strftime("%M:%S", 

2376 time.localtime(sum(p.info['cpu_times']))) 

2377 else: 

2378 cputime = '' 

2379 

2380 user = p.info['username'] or '' 

2381 if not user and POSIX: 

2382 try: 

2383 user = p.uids()[0] 

2384 except Error: 

2385 pass 

2386 if user and WINDOWS and '\\' in user: 

2387 user = user.split('\\')[1] 

2388 user = user[:9] 

2389 vms = bytes2human(p.info['memory_info'].vms) if \ 

2390 p.info['memory_info'] is not None else '' 

2391 rss = bytes2human(p.info['memory_info'].rss) if \ 

2392 p.info['memory_info'] is not None else '' 

2393 memp = round(p.info['memory_percent'], 1) if \ 

2394 p.info['memory_percent'] is not None else '' 

2395 nice = int(p.info['nice']) if p.info['nice'] else '' 

2396 if p.info['cmdline']: 

2397 cmdline = ' '.join(p.info['cmdline']) 

2398 else: 

2399 cmdline = p.info['name'] 

2400 status = p.info['status'][:5] if p.info['status'] else '' 

2401 

2402 line = templ % ( 

2403 user[:10], 

2404 p.info['pid'], 

2405 memp, 

2406 vms, 

2407 rss, 

2408 nice, 

2409 status, 

2410 ctime, 

2411 cputime, 

2412 cmdline) 

2413 print(line[:get_terminal_size()[0]]) # NOQA 

2414 

2415 

2416del memoize_when_activated, division 

2417if sys.version_info[0] < 3: 

2418 del num, x 

2419 

2420if __name__ == "__main__": 

2421 test()