浏览代码

Finalized port closing and error warning. (#391)

Alek Petuskey 2 年之前
父节点
当前提交
450576bbee
共有 2 个文件被更改,包括 63 次插入7 次删除
  1. 14 2
      pynecone/pc.py
  2. 49 5
      pynecone/utils.py

+ 14 - 2
pynecone/pc.py

@@ -8,6 +8,8 @@ import typer
 
 from pynecone import constants, utils
 
+from rich.prompt import Prompt
+
 # Create the app.
 cli = typer.Typer()
 
@@ -60,6 +62,16 @@ def run(
     port: str = typer.Option(None, help="Specify a different port."),
 ):
     """Run the app in the current directory."""
+    frontend_port = utils.get_config().port if port is None else port
+    backend_port = utils.get_api_port()
+
+    # If something is running on the ports, ask the user if they want to kill it.
+    if utils.is_process_on_port(frontend_port):
+        utils.terminate_port(frontend_port, "frontend")
+
+    if utils.is_process_on_port(backend_port):
+        utils.terminate_port(backend_port, "backend")
+
     # Check that the app is initialized.
     if frontend and not utils.is_initialized():
         utils.console.print(
@@ -93,8 +105,8 @@ def run(
         if backend:
             backend_cmd(app.__name__, loglevel=loglevel)
     finally:
-        utils.kill_process_on_port(os.environ["PORT"])
-        utils.kill_process_on_port(utils.get_api_port())
+        utils.kill_process_on_port(frontend_port)
+        utils.kill_process_on_port(backend_port)
 
 
 @cli.command()

+ 49 - 5
pynecone/utils.py

@@ -37,6 +37,7 @@ import uvicorn
 from plotly.io import to_json
 from redis import Redis
 from rich.console import Console
+from rich.prompt import Prompt
 
 from pynecone import constants
 from pynecone.base import Base
@@ -582,20 +583,63 @@ def get_api_port() -> int:
     return port
 
 
-def kill_process_on_port(port):
-    """Kill the process on the given port.
+def get_process_on_port(port) -> Optional[psutil.Process]:
+    """Get the process on the given port.
 
     Args:
         port: The port.
+
+    Returns:
+        The process on the given port.
     """
     for proc in psutil.process_iter(["pid", "name", "cmdline"]):
         try:
             for conns in proc.connections(kind="inet"):
-                if conns.laddr.port == port:
-                    proc.kill()
-                    return
+                if conns.laddr.port == int(port):
+                    return proc
         except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
             pass
+    return None
+
+
+def is_process_on_port(port) -> bool:
+    """Check if a process is running on the given port.
+
+    Args:
+        port: The port.
+
+    Returns:
+        Whether a process is running on the given port.
+    """
+    return get_process_on_port(port) is not None
+
+
+def kill_process_on_port(port):
+    """Kill the process on the given port.
+
+    Args:
+        port: The port.
+    """
+    if get_process_on_port(port) is not None:
+        get_process_on_port(port).kill()  # type: ignore
+
+
+def terminate_port(port, _type):
+    """Terminate the port.
+
+    Args:
+        port: The port.
+        _type: The type of the port.
+    """
+    console.print(
+        f"Something is already running on port [bold underline]{port}[/bold underline]. This is the port the {_type} runs on."
+    )
+    frontend_action = Prompt.ask("Kill it?", choices=["y", "n"])
+    if frontend_action == "y":
+        kill_process_on_port(port)
+    else:
+        console.print("Exiting...")
+        sys.exit()
 
 
 def run_backend(app_name: str, loglevel: constants.LogLevel = constants.LogLevel.ERROR):