def print_ps_info(file=sys.stderr):
    """Print process summary info from psutil

    warns if psutil is unavailable
    """
    try:
        import psutil
    except ImportError:
        # nothing to print
        warnings.warn(
            "psutil unavailable. Install psutil to get CPU and memory stats",
            stacklevel=2,
        )
        return
    p = psutil.Process()
    # format CPU percentage
    cpu = p.cpu_percent(0.1)
    if cpu >= 10:
        cpu_s = str(int(cpu))
    else:
        cpu_s = f"{cpu:.1f}"

    # format memory (only resident set)
    rss = p.memory_info().rss
    if rss >= 1e9:
        mem_s = f'{rss / 1e9:.1f}G'
    elif rss >= 1e7:
        mem_s = f'{rss / 1e6:.0f}M'
    elif rss >= 1e6:
        mem_s = f'{rss / 1e6:.1f}M'
    else:
        mem_s = f'{rss / 1e3:.0f}k'

    # left-justify and shrink-to-fit columns
    cpulen = max(len(cpu_s), 4)
    memlen = max(len(mem_s), 3)
    fd_s = str(p.num_fds())
    fdlen = max(len(fd_s), 3)
    threadlen = len('threads')

    print(
        "{} {} {} {}".format(
            '%CPU'.ljust(cpulen), 'MEM'.ljust(memlen), 'FDs'.ljust(fdlen), 'threads'
        ),
        file=file,
    )

    print(
        f"{cpu_s.ljust(cpulen)} {mem_s.ljust(memlen)} {fd_s.ljust(fdlen)} {str(p.num_threads()).ljust(7)}",
        file=file,
    )

    # trailing blank line
    print('', file=file)
Print process summary info from psutil

warns if psutil is unavailable
jupyterhub/utils.py