1

我希望我的 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 的值。

4

3 回答 3

3

只需全局定义“p = psutil.Process()”(在 stat() 函数之外)。cpu_percent() 跟踪自上次调用以来的 CPU 时间,这就是它能够确定百分比的方式。

第一次调用将始终为 0.0,因为计算百分比需要随着时间的推移比较两个值,因此,必须经过一段时间。

于 2016-11-28T01:49:43.593 回答
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,然后在 main 中导入模块并启动监视循环。

import monitor
monitor.start_monitor()

然后在每个请求调用中:

monitor.cpu_averages()

并在您认为有意义的时间段内提取价值。

于 2016-11-28T02:32:31.073 回答
0

格雷厄姆的解决方案似乎有效,但是我找到了一种更简单的解决方案,通过告诉它间隔,在这个例子中它测量最后一秒:

psutil.cpu_percent(interval=1)
于 2022-01-05T16:59:45.150 回答