<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def nbopen(filename):
 """ Open a notebook using the best available server. Returns information about the selected server. """

    filename = osp.abspath(filename)
    home_dir = get_home_dir()
    server_info = find_best_server(filename)

    if server_info is not None:
        print("Using existing server at", server_info['notebook_dir'])
        return server_info
    else:
        if filename.startswith(home_dir):
            nbdir = home_dir
        else:
            nbdir = osp.dirname(filename)

        print("Starting new server")
        command = [sys.executable, '-m', 'notebook', '--no-browser',
                   '--notebook-dir={}'.format(nbdir),
                   '--NotebookApp.password=',
                   "--KernelSpecManager.kernel_spec_class='{}'".format(
                           KERNELSPEC)]

        if os.name == 'nt':
            creation_flag = 0x08000000  # CREATE_NO_WINDOW
        else:
            creation_flag = 0  # Default value

        if DEV:
            env = os.environ.copy()
            env["PYTHONPATH"] = osp.dirname(get_module_path('spyder'))
            proc = subprocess.Popen(command, creationflags=creation_flag,
                                    env=env)
        else:
            proc = subprocess.Popen(command, creationflags=creation_flag)

        # Kill the server at exit. We need to use psutil for this because
        # Popen.terminate doesn't work when creationflags or shell=True
        # are used.
        def kill_server_and_childs(pid):
            ps_proc = psutil.Process(pid)
            for child in ps_proc.children(recursive=True):
                child.kill()
            ps_proc.kill()

        atexit.register(kill_server_and_childs, proc.pid)

        # Wait ~25 secs for the server to be up
        for _x in range(100):
            server_info = find_best_server(filename)
            if server_info is not None:
                break
            else:
                time.sleep(0.25)

        if server_info is None:
            raise NBServerError()

        return server_info