2016-11-27 59 views
0

我想我的瓶的應用程序來報告它當前正在使用的百分比有多少CPU和內存:psutil的cpu_percent總是返回0.0

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() 

當發送大量請求,到/測試/統計永遠對於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

這是一種自我指涉;該應用程序將消耗額外的週期和內存來報告它已經消耗了多少個週期和內存。這可以通過其他過程監控應用程序和服務來完成;你爲什麼想在你的應用程序中使用它? – Makoto

回答

1

只需在全局(stat()函數外)定義「p = psutil.Process()」即可。 cpu_percent()記錄自上次調用以來的CPU時間,這就是它如何確定百分比。

第一次調用將始終爲0.0,因爲計算百分比是需要隨時間比較兩個值的事情,因此需要一段時間。

1

正如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() 

和提取價值,你覺得有道理。