我希望我的Flask应用程序以百分比的形式报告当前使用的CPU和内存:
import psutil
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/test", methods=["GET"])
def healthz():
return jsonify(msg="OK"), 200
@app.route("/stats", methods=["GET"])
def stats():
p = psutil.Process()
json_body = {
"cpu_percent": p.cpu_percent(interval=None),
"cpu_times": p.cpu_times(),
"mem_info": p.memory_info(),
"mem_percent": p.memory_percent()
}
return jsonify(json_body), 200
def main():
app.run(host="0.0.0.0", port=8000, debug=False)
if __name__ == '__main__':
main()
在向/ test发送大量请求时,/ stats将始终为cpu_percent返回0.0:
$ while true; do curl http://127.0.0.1:8000/test &>/dev/null; done &
$ curl http://127.0.0.1:8000/stats
{
"cpu_percent": 0.0,
"cpu_times": [
4.97,
1.28,
0.0,
0.0
],
"mem_info": [
19652608,
243068928,
4292608,
4096,
0,
14675968,
0
],
"mem_percent": 1.8873787935409003
}
但是,如果我使用ipython手动检查:
import psutil
p = psutil.Process(10993)
p.cpu_percent()
这正确返回大于0.0的值。
答案 0 :(得分:2)
只需在全局范围内定义“p = psutil.Process()”(在stat()函数之外)。 cpu_percent()跟踪自上次调用以来的CPU时间,这就是它如何确定百分比。
第一次调用将始终为0.0,因为计算百分比需要随时间比较两个值,因此,必须经过一段时间。
答案 1 :(得分:2)
正如Giampaolo指出的那样,Process
的实例需要处于全局范围,因为实例会根据先前的调用跟踪状态以进行处理。
请注意,虽然CPU百分比可以从一个时刻到另一个时刻跳得很多,特别是在计算的时间段不断变化的情况下,可能会非常混乱。使用后台线程可能会更好,它可以在设定的时间范围内计算出CPU百分比平均值。
我碰巧使用的一些代码可能很有用:
from __future__ import print_function
import os
import time
import atexit
import threading
try:
import Queue as queue
except ImportError:
import queue
import psutil
_running = False
_queue = queue.Queue()
_lock = threading.Lock()
_cpu_percentage = 1800 * [0.0]
_processes = {}
def _monitor():
global _cpu_percentage
global _processes
while True:
marker = time.time()
total = 0.0
pids = psutil.pids()
processes = {}
for pid in pids:
process = _processes.get(pid)
if process is None:
process = psutil.Process(pid)
processes[pid] = process
total += process.cpu_percent()
_processes = processes
_cpu_percentage.insert(0, total)
_cpu_percentage = _cpu_percentage[:1800]
duration = max(0.0, 1.0 - (time.time() - marker))
try:
return _queue.get(timeout=duration)
except queue.Empty:
pass
_thread = threading.Thread(target=_monitor)
_thread.setDaemon(True)
def _exiting():
try:
_queue.put(True)
except Exception:
pass
_thread.join()
def track_changes(path):
if not path in _files:
_files.append(path)
def start_monitor():
global _running
_lock.acquire()
if not _running:
prefix = 'monitor (pid=%d):' % os.getpid()
print('%s Starting CPU monitor.' % prefix)
_running = True
_thread.start()
atexit.register(_exiting)
_lock.release()
def cpu_averages():
values = _cpu_percentage[:60]
averages = {}
def average(secs):
return min(100.0, sum(values[:secs])/secs)
averages['cpu.average.1s'] = average(1)
averages['cpu.average.5s'] = average(5)
averages['cpu.average.15s'] = average(15)
averages['cpu.average.30s'] = average(30)
averages['cpu.average.1m'] = average(60)
averages['cpu.average.5m'] = average(300)
averages['cpu.average.15m'] = average(900)
averages['cpu.average.30m'] = average(1800)
return averages
我有其他的东西,我删除了,所以希望剩下的东西仍处于可用状态。
要使用它,请添加到文件monitor.py
,然后导入主文件中的模块并启动监控循环。
import monitor
monitor.start_monitor()
然后在每个请求呼叫上:
monitor.cpu_averages()
并提取您认为有意义的时间段的值。