1. 程式人生 > >python3之模塊psutil系統性能信息

python3之模塊psutil系統性能信息

雙工 .org import llb stream mem hello AI 數量

psutil是個跨平臺庫,能夠輕松實現獲取系統運行的進程和系統利用率,包括CPU、內存、磁盤、網絡等信息。

它主要應用於信息監控,分析和限制系統資源及進程的管理。它實現了同等命令命令行工具提供的功能,如:ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等。目前支持32位和64位的linux、windows、OS X、FreeBSD和Sun Solaris等操作系統。

1、psutil模塊安裝

(1)源碼安裝psutil

git clone https://
github.com/giampaolo/psutil.git cd psutil python3 setup.py install

(2)pip安裝

pip3 install psutil

(3)windows上安裝

C:\python35\python.exe -m pip install psutil

或者源碼編譯安裝:
make.bat build
make.bat install

2、獲取CPU信息

In [10]: psutil.cpu_times(percpu=False)  #查看CPU所有信息
Out[10]: scputimes(user=306.98, nice=2.01, system=337.34, idle=410414.39, iowait=78.37, irq=0.0, softirq=17.42, steal=0.0, guest=0.0, guest_nice=0.0)

#user:用戶進程花費的時間 #nice:用戶模式執行Niced優先級進程花費的時間 #system:內核模式進程花費的時間 #idle:閑置時間 #iowait:等待I/O完成的時間 #irq:處理硬件中斷的時間 #softirq:處理軟件中斷的時間 #steal:虛擬化環境中運行的其他操作系統花費的時間 #guest:在linux內核的控制下為客戶端操作系統運行虛擬CPU所花費的時間 #guest_nice:虛擬機運行niced所花費的時間

#顯示CPU所有邏輯信息

In [7]: psutil.cpu_times(percpu=True)  #顯示所有CPU邏輯信息
Out[7]: [scputimes(user=45.48, nice=0.31, system=69.41, idle=101285.67, iowait=19.67, irq=0.0, softirq=3.06, steal=0.0, guest=0.0, guest_nice=0.0), scputimes(user=110.04, nice=0.46, system=70.63, idle=101210.2, iowait=22.99, irq=0.0, softirq=5.0, steal=0.0, guest=0.0, guest_nice=0.0), scputimes(user=58.5, nice=0.5, system=126.64, idle=100934.59, iowait=14.47, irq=0.0, softirq=4.36, steal=0.0, guest=0.0, guest_nice=0.0), scputimes(user=92.1, nice=0.72, system=68.3, idle=101146.96, iowait=21.12, irq=0.0, softirq=4.79, steal=0.0, guest=0.0, guest_nice=0.0)]

#顯示用戶占CPU的時間比

In [11]: psutil.cpu_times().user  #顯示用戶占CPU的時間比
Out[11]: 307.11

#顯示CPU邏輯個數和物理個數

In [8]: psutil.cpu_count(logical=True)  #顯示CPU邏輯個數
Out[8]: 4

In [9]: psutil.cpu_count(logical=False)  #顯示CPU物理個數
Out[9]: 4

#將各種CPU統計信息作為命名元組返回

In [15]: psutil.cpu_stats()   #CPU統計信息
Out[15]: scpustats(ctx_switches=9838934, interrupts=10572621, soft_interrupts=5582125, syscalls=0)

#ctx_switches:啟動後的上下問切換次數
#interrupts:自啟動以來的中斷次數
#soft_interrupts:啟動後的軟件中斷數量
#syscalls:啟動以來的系統調用次數,在linux上始終為0

3、內存信息

psutil.virtual_memory()以字節返回內存使用情況的統計信息

In [20]: mem = psutil.virtual_memory()  #獲取內存完整信息
In [21]: mem
Out[21]: svmem(total=2078892032, available=1508818944, percent=27.4, used=367063040, free=135192576, active=874614784, inactive=694231040, buffers=122880, cached=1576513536, shared=10444800, slab=255148032)

#total:總物理內存
#available:可用的內存
#used:使用的內存
#free:完全沒有使用的內存
#active:當前正在使用的內存
#inactive:標記為未使用的內存
#buffers:緩存文件系統元數據使用的內存
#cached:緩存各種文件的內存
#shared:可以被多個進程同時訪問的內存
#slab:內核數據結構緩存的內存


In [22]: mem.total  #獲取內存總數
Out[22]: 2078892032

In [23]: mem.used  #獲取已使用內存
Out[23]: 367063040

In [24]: mem.free  #獲取空閑內存
Out[24]: 135192576

In [25]: psutil.swap_memory()  #獲取swap內存信息
Out[25]: sswap(total=2148528128, used=270336, free=2148257792, percent=0.0, sin=0, sout=12288)

#total:以字節為單位的總交換內存
#used:以字節為單位使用交換內存
#free:以字節為單位的可用交換內存
#percent:使用百分比
#sin:系統從磁盤交換的字節數
#sout:系統從磁盤換出的字節數

4、磁盤信息

psutil.disk_partitions(all=False):返回所有安裝的磁盤分區作為名稱元組的列表,包括設備,安裝點和文件系統類型,類似於Unix上的‘df’命令.

In [25]: import psutil
In [26]: psutil.disk_partitions(all=False) #獲取磁盤完整信息
Out[26]: 
[sdiskpart(device=/dev/sda3, mountpoint=/, fstype=xfs, opts=rw,seclabel,relatime,attr2,inode64,noquota),
 sdiskpart(device=/dev/sda5, mountpoint=/home, fstype=xfs, opts=rw,seclabel,relatime,attr2,inode64,noquota),
 sdiskpart(device=/dev/sda1, mountpoint=/boot, fstype=xfs, opts=rw,seclabel,relatime,attr2,inode64,noquota)]

psutil.disk_usage(path):將有關包含給定路徑的分區的磁盤使用情況統計信息返回為指定元組,包括以字節表示的,總共,已使用和空閑的空間以及百分比使用率,如果路徑存在則引發OSError.

In [30]: psutil.disk_usage(/)  #獲取分區使用情況
Out[30]: sdiskusage(total=53660876800, used=3662462976, free=49998413824, percent=6.8)

#total:總的大小(字節)
#used:已使用的大小(字節)
#free:空閑的大小(字節)
#percent:使用百分比

psutil.disk_io_counters(perdisk=False,nowrap=True) #將系統範圍的磁盤I/0統計作為命名元組返回,包括以下字段:

  • read_count:讀取次數
  • write_count:寫入次數
  • read_bytes:讀取的字節數
  • write_bytes:寫入的字節數
  • read_time:從磁盤讀取的時間(以毫秒為單位)
  • write_time:寫入磁盤的時間(毫秒為單位)
  • busy_time:花費在實際I/O上的時間
  • read_merged_count:合並讀取的數量
  • write_merged_count:合並寫入次數

perdisk為True時返回物理磁盤相同的信息;nowrap為True它將檢測並調整函數調用中的新值。

In [32]: psutil.disk_io_counters(perdisk=True)  #獲取單個分區的IO信息
Out[32]: 
{fd0: sdiskio(read_count=0, write_count=0, read_bytes=0, write_bytes=0, read_time=0, write_time=0, read_merged_count=0, write_merged_count=0, busy_time=0),
 sda1: sdiskio(read_count=1003, write_count=25, read_bytes=5893632, write_bytes=2226176, read_time=1143, write_time=11298, read_merged_count=0, write_merged_count=1, busy_time=3976),
 sda2: sdiskio(read_count=51, write_count=2, read_bytes=2260992, write_bytes=12288, read_time=246, write_time=391, read_merged_count=0, write_merged_count=1, busy_time=545),
 sda3: sdiskio(read_count=15216, write_count=34370, read_bytes=456854528, write_bytes=2394566656, read_time=186146, write_time=3937459, read_merged_count=17, write_merged_count=37260, busy_time=156705),

5、網絡信息

psutil.net_io_counters(pernic=False,nowrap=True):將系統範圍的網絡I/O統計信息作為命名元組返回,包括以下屬性:

  • bytes_sent:發送的字節數
  • bytes_recv:收到的字節數
  • packets_sent:發送的數據包數量
  • packets_recv:接收的數據包數量
  • errin:接收時的錯誤總數
  • errout:發送時的錯誤總數
  • dropin:丟棄的傳入數據包總數
  • dripout:丟棄的傳出數據包總數(在OSX和BSD上始終為0)

如果pernic為True網絡接口上安裝的每個網絡接口返回相同的信息,nowrap為True時將檢測並調整函數調用中的這些數字,將舊值添加到新值,保證返回的數字將增加或不變,但不減少,net_io_counters.cache_clear()可用於使nowrap緩存失效。

In [79]: psutil.net_io_counters(pernic=False,nowrap=True)
Out[79]: snetio(bytes_sent=19487039, bytes_recv=301660567, packets_sent=123489, packets_recv=337983, errin=0, errout=0, dropin=0, dropout=0)

In [81]: psutil.net_io_counters(pernic=True,nowrap=True)
Out[81]: 
{ens32: snetio(bytes_sent=17684066, bytes_recv=299856862, packets_sent=121275, packets_recv=335825, errin=0, errout=0, dropin=0, dropout=0),
 lo: snetio(bytes_sent=1812739, bytes_recv=1812739, packets_sent=2270, packets_recv=2270, errin=0, errout=0, dropin=0, dropout=0)}

psutil.net_connections(kind=‘inet‘):返回系統範圍的套接字鏈接,命令元組列表返回,每個命名元組提供了7個屬性:

  • fd:套接字文件描述符。
  • family:地址系列,AF_INET, AF_INET6 或AF_UNIX。
  • type:地址類型,SOCK_STREAM或 SOCK_DGRAM。
  • laddr:本地地址作為命名元組或 AF_UNIX套接字的情況。對於UNIX套接字,請參閱下面的註釋。(ip, port)path
  • raddr:遠程地址是指定的元組,或者是UNIX套接字的絕對地址當遠程端點未連接時,您將獲得一個空元組(AF_INET *)或(AF_UNIX)。對於UNIX套接字,請參閱下面的註釋。(ip, port)path""
  • status:表示TCP連接的狀態。
  • pid:打開套接字的進程的PID,如果是可檢索的,否則None在某些平臺(例如Linux)上,此字段的可用性根據進程權限而變化(需要root)。

kind參數的值包括:

inet:ipv4和ipv6

inet4:ipv4

inet6:ipv6

tcp:TCP

tcp4:TCP over ipv4

tcp6:TCP over ipv6

udp:UDP

dup4:基於ipv4的udp

cpu6:基於ipv6的udp

Unix:UNIX套接字(udp和TCP協議)

all:所有可能的家庭和協議的總和

In [86]: psutil.net_connections(kind=tcp)
Out[86]: 
[sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=9090), raddr=(), status=LISTEN, pid=103599),
 sconn(fd=4, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=::, port=22), raddr=(), status=LISTEN, pid=1179),
 sconn(fd=13, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=25), raddr=(), status=LISTEN, pid=1279),
 sconn(fd=10, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=0.0.0.0, port=3306), raddr=(), status=LISTEN, pid=70099),
 sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=0.0.0.0, port=22), raddr=(), status=LISTEN, pid=1179),
 sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=192.168.146.139, port=22), raddr=addr(ip=192.168.146.1, port=4238), status=ESTABLISHED, pid=122738),
 sconn(fd=12, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=9001), raddr=(), status=LISTEN, pid=103596),
 sconn(fd=14, family=<AddressFamily.AF_INET6: 10>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=::1, port=25), raddr=(), status=LISTEN, pid=1279)]

In [87]: psutil.net_connections(kind=inet4)
Out[87]: 
[sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=9090), raddr=(), status=LISTEN, pid=103599),
 sconn(fd=13, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=25), raddr=(), status=LISTEN, pid=1279),
 sconn(fd=10, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=0.0.0.0, port=3306), raddr=(), status=LISTEN, pid=70099),
 sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=0.0.0.0, port=22), raddr=(), status=LISTEN, pid=1179),
 sconn(fd=3, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=192.168.146.139, port=22), raddr=addr(ip=192.168.146.1, port=4238), status=ESTABLISHED, pid=122738),
 sconn(fd=6, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_DGRAM: 2>, laddr=addr(ip=0.0.0.0, port=68), raddr=(), status=NONE, pid=119605),
 sconn(fd=12, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=127.0.0.1, port=9001), raddr=(), status=LISTEN, pid=103596),
 sconn(fd=1, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_DGRAM: 2>, laddr=addr(ip=127.0.0.1, port=323), raddr=(), status=NONE, pid=741)]

psutil.net_if_addrs():以字典的方式返回系統上的每個網絡接口的關聯地址。

In [88]: psutil.net_if_addrs()
Out[88]: 
{lo: [snic(family=<AddressFamily.AF_INET: 2>, address=127.0.0.1, netmask=255.0.0.0, broadcast=None, ptp=None),
  snic(family=<AddressFamily.AF_INET6: 10>, address=::1, netmask=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff, broadcast=None, ptp=None),
  snic(family=<AddressFamily.AF_PACKET: 17>, address=00:00:00:00:00:00, netmask=None, broadcast=None, ptp=None)],
 ens32: [snic(family=<AddressFamily.AF_INET: 2>, address=192.168.146.139, netmask=255.255.255.0, broadcast=192.168.146.255, ptp=None),
  snic(family=<AddressFamily.AF_INET6: 10>, address=fe80::9853:19bb:b07b:89d4%ens32, netmask=ffff:ffff:ffff:ffff::, broadcast=None, ptp=None),
  snic(family=<AddressFamily.AF_PACKET: 17>, address=00:50:56:31:d8:11, netmask=None, broadcast=ff:ff:ff:ff:ff:ff, ptp=None)]}

psutil.net_if_stats():將安裝在系統上的網絡接口的信息作為字典返回,其中包括isup是否啟動,duplex雙工模式,speed速率,mtu最大傳輸單位,以字節表示

In [89]: psutil.net_if_stats()
Out[89]: 
{ens32: snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1000, mtu=1500),
 lo: snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)}

6、其他系統信息

IN[93]:import psutil,time
In [94]: psutil.boot_time()  #系統啟動時間戳
Out[94]: 1527457908.0
In [96]: time.strftime(%Y-%m-%d %H:%M:%S,time.localtime(psutil.boot_time
    ...: ()))    #格式化時間
Out[96]: 2018-05-28 05:51:48

In [97]: psutil.users()   #返回當前鏈接的系統用戶
Out[97]: 
[suser(name=root, terminal=tty1, host=‘‘, started=1527050368.0, pid=769),
 suser(name=root, terminal=pts/0, host=192.168.146.1, started=1527559040.0, pid=122742),
 suser(name=root, terminal=pts/1, host=192.168.146.1, started=1527559040.0, pid=122761)]

7、系統進程管理

In [1]: import psutil

In [2]: psutil.pids()   #列出所有進程PID
Out[2]: 
[1,2,3,5,6,7,8,]

In [3]: p = psutil.Process(1265)  #實例化一個Process對象,參數為進程PID

In [4]: p.name()  #進程名
Out[4]: mysqld

In [5]: p.exe()  #進程bin路徑
Out[5]: /usr/local/mysql-5.5.32/bin/mysqld

In [6]: p.cwd()  #進程工作目錄絕對路徑
Out[6]: /mysql/data

In [7]: p.status()  #進程狀態
Out[7]: sleeping

In [8]: p.create_time()  #進程創建時間,時間戳格式
Out[8]: 1527642963.22

In [9]: p.uids()  #進程UID信息
Out[9]: puids(real=1001, effective=1001, saved=1001)

In [10]: p.gids()  #進程GID信息
Out[10]: pgids(real=1001, effective=1001, saved=1001)

In [11]: p.cpu_times()  #進程CPU時間信息,包括user、system的CPU時間
Out[11]: pcputimes(user=1.53, system=6.06, children_user=0.0, children_system=0.0)

In [12]: p.cpu_affinity()  #get進程CPU親和度,如果設置進程CPU親和度,將CPU號作為參數即可
Out[12]: [0, 1, 2, 3]

In [13]: p.memory_info()  #進程內存rss、vms信息
Out[13]: pmem(rss=45268992, vms=460525568, shared=4399104, text=9420800, lib=0, data=425431040, dirty=0)

In [14]: p.io_counters()  #進程IO信息包括讀寫IO數及字節數
Out[14]: pio(read_count=594, write_count=27, read_bytes=15859712, write_bytes=32768, read_chars=6917150, write_chars=1555)

In [15]: p.connections()  #返回發開進程socket的namedutples列表,包括fs、family、laddr等信息
Out[15]: [pconn(fd=10, family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, laddr=addr(ip=0.0.0.0, port=3306), raddr=(), status=LISTEN)]

In [16]: p.num_threads()  #進程開啟的線程數
Out[16]: 16

In [17]: p.memory_percent()  #進程內存利用率
Out[17]: 2.177553778800572

psutil.process_iter(attrs=None,ad_value=None):返回一個叠代器process,為本地機器上的所有正在運行的進程生成一個類實例。

psutil.pid_exists(pid):檢查給定的PID是否存在於當前進程列表中。

psutil.wait_procs(procs,timeout=None,callback=None):等待process終止實例列表的便捷函數,返回一個元組,指示哪些進程已經消失,哪些進程還活著。

class psutil.Popen(*args,**kwargs):它啟動一個子進程,並完全像使用subprocess.Popen一樣處理,它還提供了所有psutil.Process類的方法。Popen類的作用是獲取用戶啟動的應用程序進程信息,以便跟蹤程序進程的運行狀態。

In [18]: import psutil

In [19]: from subprocess import PIPE

In [20]: p = psutil.Popen(["/usr/bin/python","-c","print(‘hello world‘)"],stdout=
    ...: PIPE)

In [21]: p.name()
Out[21]: python

In [22]: p.username()
Out[22]: root

In [23]: p.communicate()
Out[23]: (bhello world\n, None)

進程過濾實例:

In [25]: import psutil

In [26]: from pprint import pprint as pp

#根據進程名查看系統中的進程名與pid
In [27]: pp([p.info for p in psutil.process_iter(attrs=[pid,name]) if python
    ...:  in p.info[name]])
[{name: ipython3, pid: 2429}]

In [28]: pp([p.info for p in psutil.process_iter(attrs=[pid,name]) if mysql
    ...:  in p.info[name]])
[{name: mysqld_safe, pid: 987}, {name: mysqld, pid: 1265}]

#所有用戶進程
In [32]: import getpass

In [33]: pp([(p.pid,p.info[name]) for p in psutil.process_iter(attrs=[name,u
    ...: sername]) if p.info[username] == getpass.getuser()])
[(1, systemd),
 (2, kthreadd),
 (3, ksoftirqd/0),
 (5, kworker/0:0H),
 (6, kworker/u256:0),
...
 (5004, kworker/0:0)]

#查看積極運行的進程:
In [37]: pp([(p.pid,p.info) for p in psutil.process_iter(attrs=[name,status])
    ...:  if p.info[status] == psutil.STATUS_RUNNING])
[(2429, {name: ipython3, status: running})]

#使用日誌文件的進程
In [38]: import os,psutil

In [39]: for p in psutil.process_iter(attrs=[name,open_files]):
    ...:     for file in p.info[open_files] or []:
    ...:         if os.path.splitext(file.path)[1] == .log:
    ...:             print("%-5s %-10s %s" % (p.pid,p.info[name][:10],file.path
    ...: ))
    ...:             
689   auditd     /var/log/audit/audit.log
725   vmtoolsd   /var/log/vmware-vmsvc.log
974   tuned      /var/log/tuned/tuned.log

#消耗超過5M內存的進程:
In [42]: pp([(p.pid,p.info[name],p.info[memory_info].rss) for p in psutil.pro
    ...: cess_iter(attrs=[name,memory_info]) if p.info[memory_info].rss > 5
    ...:  * 1024 * 1024])
[(1, systemd, 7118848),
 (411, systemd-udevd, 6254592),
 (712, polkitd, 13553664),
 (716, abrtd, 5734400),
 (724, VGAuthService, 6262784),
 (725, vmtoolsd, 6426624),
 (974, tuned, 19648512),
 (1265, mysqld, 45268992),
 (2204, sshd, 5726208),
 (2429, ipython3, 37232640)]


#消耗量最大的3個進程
In [43]: pp([(p.pid, p.info) for p in sorted(psutil.process_iter(attrs=[name,     ...: memory_percent]), key=lambda p: p.info[memory_percent])][-3:])
[(974, {memory_percent: 0.9451434561080659, name: tuned}),
 (2429, {memory_percent: 1.7909847854955845, name: ipython3}),
 (1265, {memory_percent: 2.177553778800572, name: mysqld})]

#消耗最多CPU時間的前3個進程
In [44]: pp([(p.pid, p.info[name], sum(p.info[cpu_times])) for p in sorted(ps
    ...: util.process_iter(attrs=[name, cpu_times]), key=lambda p: sum(p.info
    ...: [cpu_times][:2]))][-3:])
[(1265, mysqld, 13.93),
 (2429, ipython3, 14.809999999999999),
 (725, vmtoolsd, 16.74)]

#導致最多I/O的前3個進程
In [45]: pp([(p.pid, p.info[name]) for p in sorted(psutil.process_iter(attrs=[    ...: name, io_counters]), key=lambda p: p.info[io_counters] and p.info[
    ...: io_counters][:2])][-3:])
[(2429, ipython3), (725, vmtoolsd), (1, systemd)]


#前3個進程打開最多的文件描述符:
In [46]: pp([(p.pid, p.info) for p in sorted(psutil.process_iter(attrs=[name,     ...: num_fds]), key=lambda p: p.info[num_fds])][-3:])
[(377, {name: systemd-journald, num_fds: 24}),
 (1, {name: systemd, num_fds: 43}),
 (1307, {name: master, num_fds: 91})]

了解更對內容請查看官方文檔:psutil.readhtedocs.io

python3之模塊psutil系統性能信息