psutil (python system and process utilities) 是一个跨平台的第三方库,能够轻松实现获取系统运行的进程和系统利用率(包扩CPU、内存、磁盘、网络等)信息。它主要用于系统监控、分析、限制系统资源和进程的管理。它实现了同等命令行工具提供的功能,如ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等。目前支持的操作系统包括:Linux,Windows,macOS,,AIX等等。同时支持python2与python3版本,当前最新版本为5.4.8。

1. psutil的安装

1
pip install psutil

2. psutil获取系统性能信息之CPU

2.1. cpu_times CPU运行时间

psutil.cpu_times(percpu = False )将每个特定状态下CPU运行的时间以元组的形式返回。

CPU运行状态 解释
user 进程执行用户态代码耗费的CPU时间。
nice 在优先级高的用户级别执行时CPU占用率的百分比。
system 内核执行系统调用所使用的CPU时间。
idle CPU空闲并且系统没有未完成的磁盘I / O请求的时间百分比。
iowait CPU等待I/O输入输出的时间
irq CPU用于维护硬件中断所花费的时间百分比。
softirq CPU用于服务软件中断所花费的时间百分比。
steal 在虚拟化环境中运行的其他操作系统所花费的时间
guest CPU用于运行虚拟处理器的时间百分比。
dpc 服务延迟过程调用所花费的时间
interrupt 服务硬件中断所花费的时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
## ubuntu系统
### 获取CPU运行的时间信息

>>> import psutil
>>> psutil.cpu_times()
scputimes(user=42.85, nice=4.64, system=40.27, idle=4864.93, iowait=5.94, irq=0.0, softirq=2.16, steal=0.0, guest=0.0, guest_nice=0.0)


### 获取每个逻辑CPU的信息

>>> psutil.cpu_times(percpu=True)
[scputimes(user=13.2, nice=1.74, system=13.84, idle=2712.55, iowait=1.62, irq=0.0, softirq=0.57, steal=0.0, guest=0.0, guest_nice=0.0),
scputimes(user=10.48, nice=0.87, system=10.49, idle=2719.36, iowait=1.45, irq=0.0, softirq=0.21, steal=0.0, guest=0.0, guest_nice=0.0),
scputimes(user=12.4, nice=1.36, system=10.22, idle=2721.21, iowait=1.37, irq=0.0, softirq=0.7, steal=0.0, guest=0.0, guest_nice=0.0),
scputimes(user=11.28, nice=0.65, system=9.2, idle=2723.23, iowait=1.5, irq=0.0, softirq=0.83, steal=0.0, guest=0.0, guest_nice=0.0)]

## windows操作系统

>>> psutil.cpu_times()
scputimes(user=10006.453125, system=5947.421875, idle=155528.3125, interrupt=209.296875, dpc=187.203125)

2.2. cpu_percent cpu利用率

psutil.cpu_percent(interval = None,percpu = False )返回一个浮点数,表示当前系统范围的CPU利用率百分比。如果interval=0.1,表示0.1sCPU的平均使用率。如果interval=0或者None时,比较自上次调用或模块导入后经过的系统CPU时间,立即返回。所有第一次的返回的数据是个无意义的数据。当percpu是True返回表示利用率的浮点数列表,以每个逻辑CPU的百分比表示。

1
2
3
4
5
6
7
8
9
10
11
#与上次调用经过时间内的cpu的使用率
>>> psutil.cpu_percent()
1.3

#当前1s内cpu的使用率
>>> psutil.cpu_percent(interval=1)
0.3

## 4个逻辑cpu的使用率
>>> psutil.cpu_percent(interval=1,percpu=True)
[1.0, 1.0, 0.0, 0.0]

2.3. cpu_times_percent 特定CPU状态的利用率

psutil.cpu_times(percpu=True)提供每个特定CPU时间的利用率百分比 。 interval和 percpu参数的含义与icpu_percent()中的含义相同。

1
2
>>> psutil.cpu_times_percent(interval=1 )
scputimes(user=0.0, nice=0.0, system=0.5, idle=99.5, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0)

2.4. cpu_count CPU的数量

psutil.cpu_count()返回系统中逻辑CPU的物理个数或者逻辑个数。

1
2
3
4
5
6
7
8
9
10
##windows操作系统 VM虚拟机双核为2个单核处理器
### 逻辑cpu个数
>>> psutil.cpu_count()
8
### 物理cpu个数
>>> psutil.cpu_count(logical=False)
4
### 当前可用cpu个数
>>> len(psutil.Process().cpu_affinity())
8

2.5. cpu_stats CPU 统计信息

cpu_stats() 将各种CPU统计信息作以元组形式返回。

CPU信息 解释
ctx_switches 启动后的上下文切换次数
interrupts 自引导以来的中断数
soft_interrupts 自引导以来的软件中断次数
syscalls 自引导以来的系统调用次数
1
2
3
4
5
6
7
8
## ubuntu系统

>>> psutil.cpu_stats()
scpustats(ctx_switches=4589481, interrupts=2532478, soft_interrupts=719197, syscalls=0)

## windows系统
>>> psutil.cpu_stats()
scpustats(ctx_switches=344724592, interrupts=270222602, soft_interrupts=0, syscalls=1234130591)

2.6. cpu_freq CPU频率

psutil.cpu_freq(percpu = False )将CPU频率作为名称包返回,包括 以Mhz表示的当前,最小和最大频率。如果percpu是True并且系统支持每CPU频率检索,则为每个CPU返回一个频率列表,否则返回包含单个元素的列表(仅支持linux系统)。如果无法确定最小值和最大值,则将它们设置为0。在Linux 当前频率上报告实时值,在所有其他平台上它代表最大值。

1
2
3
4
5
6
7
8
9
10
11
## windows系统

>>> psutil.cpu_freq()
scpufreq(current=2594.0, min=0.0, max=2594.0)
>>> psutil.cpu_freq(percpu=False)
scpufreq(current=2594.0, min=0.0, max=2594.0)


wmic:root\cli>cpu list brief
DeviceID Manufacturer MaxClockSpeed
CPU0 GenuineIntel 2594

3 psutil获取系统性能信息之内存

3.1. virtual_memory() 物理内存使用情况

内存信息 解释
total 总物理内存
available 在没有系统进入SWAP下立即提供的内存。
percent 使用内存占比
used 使用的物理内存
free 没有使用的物理内存
active 当前正在使用或最近使用的物理内存
inactive 标记未使用的内存
buffers buffers使用的缓存
cached ccached使用的缓存
shared 显示被共享使用的物理内存大小
slab 内核数据结构缓存
1
2
3
4
5
6
7
8
9
#windows

>>> psutil.virtual_memory()
svmem(total=8473522176, available=1940721664, percent=77.1, used=6532800512, free=1940721664)

#Linux

>>> psutil.virtual_memory()
svmem(total=2070257664, available=777777152, percent=62.4, used=1090142208, free=80498688, active=1195728896, inactive=459780096, buffers=164036608, cached=735580160, shared=10145792, slab=221949952)

3.2. swap_memory() 交换内存使用情况

1
2
3
4
5
6
7
8
9
10
11
#Windows上的sin和sout总是设置为0

>>> psutil.swap_memory()
sswap(total=10151243776, used=7573495808, free=2577747968, percent=74.6, sin=0, sout=0)

#Linux
# sin:系统从磁盘累计换入的字节数
#sout:系统从磁盘累计换出的字节数

>>> psutil.swap_memory()
sswap(total=2144333824, used=7090176, free=2137243648, percent=0.3, sin=0, sout=6705152)

4 psutil获取系统性能信息之此磁盘

4.1. disk_partitions 获取所有磁盘信息

1
2
3
4
5
6
7
8
9
10
11
12
#windows

>>> from psutil import *
>>> disk_partitions()
[sdiskpart(device='C:\\', mountpoint='C:\\', fstype='NTFS', opts='rw,fixed'), #固态硬盘
sdiskpart(device='D:\\', mountpoint='D:\\', fstype='FAT32', opts='rw,removable'), #U盘
sdiskpart(device='E:\\', mountpoint='E:\\', fstype='', opts='cdrom')] #光盘

#Linux

>>> psutil.disk_partitions()
[sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,relatime,errors=remount-ro')]

4.2. disk_usage 获取单个磁盘信息

1
2
3
4
5
6
7
8
9
10
11
12
# windows

>>> disk_usage('C:\\')
sdiskusage(total=126491697152, used=86524149760, free=39967547392, percent=68.4)
>>> disk_usage('D:\\')
sdiskusage(total=134184173568, used=1953497088, free=132230676480, percent=1.5)
>>> disk_usage('E:\\')
PermissionError: [WinError 21] 设备未就绪。

# linux
>>> psutil.disk_usage("/dev/sda1")
sdiskusage(total=1016070144, used=0, free=1016070144, percent=0.0)

4.3. psutil.disk_io_counters 获取IO信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#如果perdisk为True系统上安装的每个物理磁盘返回信息

# widows

>>> disk_io_counters()
sdiskio(read_count=870403, write_count=665904, read_bytes=36953495552, write_bytes=20282217984, read_time=1565, write_time=871)

#linux

>>> psutil.disk_io_counters()
sdiskio(read_count=53366, #读取次数
write_count=9803, #写入次数
read_bytes=709110784, #读取字节数
write_bytes=417996800, #写入字节数
read_time=29572, #读取时间
write_time=4656, #写入时间
read_merged_count=1034, #合并读取的次数
write_merged_count=10158,#合并写入的次数
busy_time=17792 #实际做I/0操作的时间
)

5 psutil获取系统性能信息之网络

5.1. psutil.net_connections 获取网络套接字

1
2
3
4
5
6
7
8
9
10
11
12
13
#windows
>>> net_connections()
[sconn(fd=-1, family=<AddressFamily.AF_INET6: 23>, type=1, laddr=addr(ip='::', port=1536), raddr=(), status='LISTEN', pid=724),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=2, laddr=addr(ip='::1', port=5353), raddr=(), status='NONE', pid=4208),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=2, laddr=addr(ip='0.0.0.0', port=58044), raddr=(), status='NONE', pid=14420),
sconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=1, laddr=addr(ip='127.0.0.1', port=36600), raddr=(), status='LISTEN', pid=6116),
sconn(fd=-1, family=<AddressFamily.AF_INET6: 23>, type=1, laddr=addr(ip='::1', port=26672), raddr=addr(ip='::1', port=35432))]


#Linux

>>> psutil.net_connections()
[sconn(fd=6, family=2, type=2, laddr=addr(ip='0.0.0.0', port=68), raddr=(), status='NONE', pid=652)]

5.2. psutil.net_if_addrs 获取网卡的信息

1
2
3
4
5
6
7
8
9
10
11
# windows

>>> net_if_addrs()
{ 'VMware Network Adapter VMnet1': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-50-56-C0-00-01', netmask=None, broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.153.1', netmask='255.255.255.0', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::4192:c5d1:8fff:98c6', netmask=None, broadcast=None, ptp=None)],
'VMware Network Adapter VMnet8': [snicaddr(family=<AddressFamily.AF_LINK: -1>, address='00-50-56-C0-00-08', netmask=None, broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.78.1', netmask='255.255.255.0', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET6: 23>, address='fe80::40d2:696a:cacb:8388', netmask=None, broadcast=None, ptp=None)],
'Loopback Pseudo-Interface 1': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET6: 23>, address='::1', netmask=None, broadcast=None, ptp=None)]}

#linux
>>> psutil.net_if_addrs()
{ 'lo': [snicaddr(family=2, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None), snicaddr(family=10, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), snicaddr(family=17, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
'eth0': [snicaddr(family=2, address='192.168.78.139', netmask='255.255.255.0', broadcast='192.168.78.255', ptp=None), snicaddr(family=10, address='fe80::20c:29ff:fef4:4e44%eth0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), snicaddr(family=17, address='00:0c:29:f4:4e:44', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}

5.3. psutil.net_if_stats 获取网络接口的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# windows

>>> net_if_stats()
{ '以太网': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1000, mtu=1500),
'VMware Network Adapter VMnet1': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
'VMware Network Adapter VMnet8': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500),
'Loopback Pseudo-Interface 1': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=1073, mtu=1500),
'WLAN': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=0, mtu=1500),
'本地连接* 2': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=0, mtu=1500),
'本地连接* 1': snicstats(isup=False, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=0, mtu=1500)}
>>>

# Linux

>>> psutil.net_if_stats()
{ 'lo': snicstats(isup=True, duplex=0, speed=0, mtu=65536), 'eth0': snicstats(isup=True, duplex=2, speed=1000, mtu=1500)}

5.4. psutil.net_io_counters 获取网口的流量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# psutil.net_io_counters(pernic = False) 如果pernic为True系统上安装的每个网络接口返回信息。
# windows

>>> net_io_counters()
snetio(bytes_sent=176300623, #发送字节
bytes_recv=402338143, #接受字节
packets_sent=2509858, #发送包数
packets_recv=713322, #接受包数
errin=0, #接受错误数
errout=0, #发送错误数
dropin=0, #丢弃传入数据包数量
dropout=0) #丢弃传出数据包数量


# Linux
>>> psutil.net_io_counters()
snetio(bytes_sent=83801, bytes_recv=31649461, packets_sent=1277, packets_recv=21180, errin=0, errout=0, dropin=0, dropout=0)

6 psutil获取系统性能信息之其他

6.1. 获取开机时间

1
2
3
>>>import datetime,psutil
>>>datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S")
'2018-11-09 15:01:10'

6.2. 获取当前用户

1
2
>>> psutil.users()
[suser(name='root', terminal=None, host='0.4.0.0', started=1541862557.0, pid=None)]

6.3. 获取PID

1
2
>>> psutil.pids()
[0, 4, 120, 404, 592, 724, 796, 816, 936, 964, 972, 344, 496, 1180, 1336, 1508, 1540, 1568, 1592, 1644, 1696, 1720]

6.4. 获取进程信息

1
2
3
4
5
6
>>> for x in  psutil.process_iter():
... print(x)
...
psutil.Process(pid=592, name='csrss.exe', started='2018-11-09 15:01:18')
psutil.Process(pid=724, name='wininit.exe', started='2018-11-09 15:01:24')
psutil.Process(pid=736, name='svchost.exe', started='2018-11-10 17:20:13')