|
import argparse |
|
import re |
|
import subprocess |
|
|
|
import pandas as pd |
|
import psutil |
|
import requests |
|
import tabulate |
|
|
|
kernel_regex = re.compile(r".+kernel-(.+)\.json") |
|
notebook_regex = re.compile(r"(https?://([^:/]+):?(\d+)?)/?(\?token=([a-z0-9]+))?") |
|
|
|
|
|
def get_proc_info(): |
|
pids = psutil.pids() |
|
|
|
# memory info from psutil.Process |
|
df_mem = [] |
|
|
|
for pid in pids: |
|
try: |
|
proc = psutil.Process(pid) |
|
cmd = " ".join(proc.cmdline()) |
|
except psutil.NoSuchProcess: |
|
continue |
|
|
|
if len(cmd) > 0 and ("jupyter" in cmd or "ipython" in cmd) and "kernel" in cmd: |
|
# kernel |
|
kernel_ID = re.sub(kernel_regex, r"\1", cmd) |
|
|
|
# memory |
|
mem = proc.memory_info()[0] / float(1e9) |
|
|
|
uname = proc.username() |
|
|
|
# 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"] |
|
return df_mem |
|
|
|
|
|
def get_running_notebooks(): |
|
notebooks = [] |
|
|
|
for n in subprocess.Popen( |
|
["jupyter", "notebook", "list"], stdout=subprocess.PIPE |
|
).stdout.readlines()[1:]: |
|
match = re.match(notebook_regex, n.decode()) |
|
if match: |
|
base_url, host, port, _, token = match.groups() |
|
notebooks.append({"base_url": base_url, "token": token}) |
|
else: |
|
print("Unknown format: {}".format(n.decode())) |
|
|
|
return notebooks |
|
|
|
|
|
def get_session_info(password=None): |
|
df_nb = [] |
|
kernels = [] |
|
|
|
for notebook in get_running_notebooks(): |
|
s = requests.Session() |
|
if notebook["token"] is not None: |
|
s.get(notebook["base_url"] + "/?token=" + notebook["token"]) |
|
else: |
|
# do a get to the base url to get the session cookies |
|
s.get(notebook["base_url"]) |
|
if password is not None: |
|
# Seems jupyter auth process has changed, need to first get a cookie, |
|
# then add that cookie to the data being sent over with the password |
|
data = {"password": password} |
|
data.update(s.cookies) |
|
s.post(notebook["base_url"] + "/login", data=data) |
|
|
|
res = s.get(notebook["base_url"] + "/api/sessions") |
|
|
|
if res.status_code != 200: |
|
raise Exception(res.json()) |
|
|
|
for sess in res.json(): |
|
kernel_ID = sess["kernel"]["id"] |
|
if kernel_ID not in kernels: |
|
kernel = { |
|
"kernel_ID": kernel_ID, |
|
"kernel_name": sess["kernel"]["name"], |
|
"kernel_state": sess["kernel"]["execution_state"], |
|
"kernel_connections": sess["kernel"]["connections"], |
|
# "notebook_url": notebook["base_url"] + "/notebook/" + sess["id"], |
|
"notebook_path": sess["path"], |
|
} |
|
kernel.update(notebook) |
|
df_nb.append(kernel) |
|
kernels.append(kernel_ID) |
|
|
|
df_nb = pd.DataFrame(df_nb) |
|
del df_nb["token"] |
|
return df_nb |
|
|
|
|
|
def parse_args(): |
|
parser = argparse.ArgumentParser(description="Find memory usage.") |
|
parser.add_argument("--password", help="password (only needed if pass-protected)") |
|
|
|
return parser.parse_args() |
|
|
|
|
|
def main(password=None, print_ascii=False): |
|
df_mem = get_proc_info() |
|
df_nb = get_session_info(password) |
|
|
|
# joining tables |
|
df = pd.merge(df_nb, df_mem, on=["kernel_ID"], how="inner") |
|
df = df.sort_values("memory_GB", ascending=False).reset_index(drop=True) |
|
if print_ascii: |
|
print(tabulate.tabulate(df, headers=(df.columns.tolist()))) |
|
return df |
|
|
|
|
|
if __name__ == "__main__": |
|
args = vars(parse_args()) |
|
main(args["password"], print_ascii=True) |
Updating it for python3?