Jupyter notebook Jupyter笔记本:每个笔记本的内存使用情况
由于用户从未关闭旧笔记本电脑,我实验室服务器(Ubuntu)上的内存不断被填满。我想更好地了解每个笔记本占用了多少内存。我可以总结每个用户运行的所有jupyter笔记本的内存使用情况(粗略),但我想得到每个笔记本的总内存使用情况,这样我就可以关闭那些特定的内存占用(或告诉其他用户关闭他/她的)。我很快把下面的代码放在一起,得到了大约mem。每个jupyter内核的使用率,但我不知道如何将内核ID与特定笔记本关联Jupyter notebook Jupyter笔记本:每个笔记本的内存使用情况,jupyter-notebook,Jupyter Notebook,由于用户从未关闭旧笔记本电脑,我实验室服务器(Ubuntu)上的内存不断被填满。我想更好地了解每个笔记本占用了多少内存。我可以总结每个用户运行的所有jupyter笔记本的内存使用情况(粗略),但我想得到每个笔记本的总内存使用情况,这样我就可以关闭那些特定的内存占用(或告诉其他用户关闭他/她的)。我很快把下面的代码放在一起,得到了大约mem。每个jupyter内核的使用率,但我不知道如何将内核ID与特定笔记本关联 import os import pwd import pandas as pd
import os
import pwd
import pandas as pd
UID = 1
EUID = 2
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
df = []
for pid in pids:
try:
ret = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read()
except IOError: # proc has already terminated
continue
# jupyter notebook processes
if len(ret) > 0 and 'share/jupyter/runtime' in ret:
process = psutil.Process(int(pid))
mem = process.memory_info()[0]
# user name for pid
for ln in open('/proc/%d/status' % int(pid)):
if ln.startswith('Uid:'):
uid = int(ln.split()[UID])
uname = pwd.getpwuid(uid).pw_name
# user, pid, memory, proc_desc
df.append([uname, pid, mem, ret])
df = pd.DataFrame(df)
df.columns = ['user', 'pid', 'memory', 'proc_desc']
df
我似乎已经为自己的问题找到了一个可行的解决方案:
import os
import pwd
import psutil
import re
import string
import json
import urllib2
import pandas as pd
UID = 1
EUID = 2
regex = re.compile(r'.+kernel-(.+)\.json')
pids = [pid for pid in os.listdir('/proc') if pid.isdigit()]
# memory info from psutil.Process
df_mem = []
for pid in pids:
try:
ret = open(os.path.join('/proc', pid, 'cmdline'), 'rb').read()
except IOError: # proc has already terminated
continue
# jupyter notebook processes
if len(ret) > 0 and 'share/jupyter/runtime' in ret:
# kernel
kernel_ID = re.sub(regex, r'\1', ret)
kernel_ID = filter(lambda x: x in string.printable, kernel_ID)
# memory
process = psutil.Process(int(pid))
mem = process.memory_info()[0] / float(1e9)
# user name for pid
for ln in open('/proc/{}/status'.format(int(pid))):
if ln.startswith('Uid:'):
uid = int(ln.split()[UID])
uname = pwd.getpwuid(uid).pw_name
# user, pid, memory, kernel_ID
df_mem.append([uname, pid, mem, kernel_ID])
df_mem = pd.DataFrame(df_mem)
df_mem.columns = ['user', 'pid', 'memory_GB', 'kernel_ID']
# notebook info from assessing ports
df_nb = []
for port in xrange(5000,30000):
sessions = None
try:
url = 'http://127.0.0.1:{}/api/sessions'.format(port)
sessions = json.load(urllib2.urlopen(url))
except urllib2.URLError:
sessions = None
if sessions:
for sess in sessions:
kernel_ID = str(sess['kernel']['id'])
notebook_path = sess['notebook']['path']
df_nb.append([port, kernel_ID, notebook_path])
df_nb = pd.DataFrame(df_nb)
df_nb.columns = ['port', 'kernel_ID', 'notebook_path']
# joining tables
df = pd.merge(df_nb, df_mem, on=['kernel_ID'], how='inner')
df.sort(['memory_GB'], ascending=False)
我在可移植性和速度方面做了一些改进 主要是,只检查笔记本电脑运行的端口,检查不同的主机名选项,改进内核进程检查,检查ipython或jupyter
import argparse
进口稀土
导入子流程
作为pd进口熊猫
导入psutil
导入请求
进口表格
kernel\u regex=re.compile(r“+kernel-(.+)\.json”)
notebook_regex=re.compile(r)(https?:/([^:/]):?(\d+)/(\?令牌=([a-z0-9]+)?)
def get_proc_info():
pids=psutil.pids()
#来自psutil.Process的内存信息
df_mem=[]
对于pid中的pid:
尝试:
proc=psutil.Process(pid)
cmd=”“.join(proc.cmdline())
除psutil.NoSuchProcess外:
持续
如果len(cmd)>0和(cmd中的“jupyter”或cmd中的“ipython”)以及cmd中的“kernel”:
#内核
kernel\u ID=re.sub(kernel\u regex,r“\1”,cmd)
#记忆
mem=proc.memory\u info()[0]/float(1e9)
uname=proc.username()
#用户、pid、内存、内核\u ID
df_mem.append([uname,pid,mem,kernel_ID])
df_mem=pd.DataFrame(df_mem)
df_mem.columns=[“用户”、“pid”、“内存\u GB”、“内核\u ID”]
返回df_mem
def让_运行_笔记本():
笔记本=[]
对于subprocess.Popen中的n(
[“jupyter”、“notebook”、“list”],stdout=subprocess.PIPE
).stdout.readlines()[1:]:
match=re.match(notebook_regex,n.decode())
如果匹配:
基本url、主机、端口、令牌=match.groups()
append({“base\u url”:base\u url,“token”:token})
其他:
打印(“未知格式:{}”。格式(n.decode())
归还笔记本
def获取会话信息(密码=无):
df_nb=[]
内核=[]
对于get_running_notebook()中的笔记本:
s=请求。会话()
如果笔记本[“令牌”]不是无:
s、 获取(笔记本[“基本url”]+“/?令牌=”+笔记本[“令牌”])
其他:
#访问基本url以获取会话cookie
s、 获取(笔记本[“基本url”])
如果密码不是“无”:
#似乎jupyter认证过程已更改,需要先获取cookie,
#然后将cookie添加到使用密码发送的数据中
数据={“密码”:密码}
数据更新(s.cookies)
s、 post(笔记本[“基本url”]+“/登录”,数据=数据)
res=s.get(笔记本[“基本url”]+“/api/sessions”)
如果资源状态\u代码!=200:
引发异常(res.json())
对于res.json()中的SES:
kernel_ID=sess[“kernel”][“ID”]
如果内核ID不在内核中:
内核={
“内核ID”:内核ID,
“内核名称”:sess[“内核”][“名称”],
“内核状态”:sess[“内核”][“执行状态”],
“内核连接”:sess[“内核”][“连接”],
#“笔记本url”:笔记本[“基本url”]+“/notebook/”+sess[“id”],
“笔记本路径”:sess[“路径”],
}
内核更新(笔记本)
df_nb.append(内核)
append(kernels\u ID)
df_nb=局部数据帧(df_nb)
del df_nb[“令牌”]
返回df_nb
def parse_args():
parser=argparse.ArgumentParser(description=“查找内存使用情况”)
parser.add_参数(“--password”,help=“password(仅当密码受保护时才需要)”)
返回parser.parse_args()
def main(密码=无,打印ascii=假):
df_mem=get_proc_info()
df_nb=获取会话信息(密码)
#连接表
df=pd.merge(df_nb,df_mem,on=[“内核ID”],how=“内部”)
df=df.sort\u值(“内存\u GB”,升序=False)。重置\u索引(drop=True)
如果使用ascii打印:
打印(tablate.tablate(df,headers=(df.columns.tolist()))
返回df
如果名称=“\uuuuu main\uuuuuuuu”:
args=vars(parse_args())
main(args[“password”],print_ascii=True)
我可能会在这个时候继续对此进行更新
编辑:代码已更新,可以使用令牌身份验证与较新版本的Jupyter一起工作,只利用
psutil使其与Windows兼容,并且可以在Python 3上工作。我无法运行此。。由于未找到带有错误的模块PackageNotFoundError:当前通道中缺少包:-pwd
。不需要pwd
的任何其他解决方案。我使用anaconda python 2.7在windows服务器上运行。我无法运行此。。由于未找到带有错误的模块PackageNotFoundError:当前通道中缺少包:-pwd
。不需要pwd
的任何其他解决方案。我使用anaconda python 2.7在windows服务器上运行。@iLightower-hmmm,我怀疑这是否能在windows上运行。它从proc获取有关进程的大部分信息,这是一种Unix方式,用于存储有关运行进程、服务等的数据。这可能为您提供了一个起点。@iLightower我已将其更新为不使用pwd
或/proc
。相反,它只使用psutil
,它应该是可移植的,并且可以在Windows上工作。@a如果在ifmain中调用它时,您应该在主参数中添加password=args([“password”])。否则,它可能会被解释为