Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

[BUG] Dash.run(debug=True, backend="fastapi") reload subprocess silently ignores reload_dirs/reload_excludes kwargs

Đang mở
#3,962 1 bình luận 1 reaction 1 người được giao Xem trên GitHub

@T4rk1n đang làm issue này rồi.

Từ ngày 27/8/2026.

Đánh giá

Issue này chưa được đánh giá.

Mô tả

bug P2 size: 1

Summary

When using the FastAPI backend, app.run(host=..., port=..., debug=True, **kwargs) (main-thread, non-Jupyter path) triggers dash/backends/_fastapi.py::FastAPIBackend.run(), which spawns python -m uvicorn <module>:<app>.server --reload as a subprocess. Extra kwargs such as reload_dirs=[...] or reload_excludes=[...] are accepted by Dash.run(..., **flask_run_options) without error and flow straight into FastAPIBackend.run()'s **kwargs — but only kwargs.get("reload") is ever read there; every other reload-related kwarg is silently dropped when building the subprocess's CLI args. The comment directly above the subprocess.Popen(...) call even says:

# Add any other kwargs as CLI args if needed
proc = subprocess.Popen(uvicorn_args, env=env)

...but nothing implements it.

Practical effect: without an explicit --reload-dir, uvicorn/watchfiles fall back to watching the entire current working directory. In any project run with cwd above the app's own package (e.g. a monorepo, or simply python path/to/app/index.py invoked from a parent directory), the reload subprocess ends up recursively watching unrelated directories — including a shared virtualenv (.venv/site-packages/...) — so any unrelated package file being touched triggers a full, spurious app reload.

Reproduction

# repro.py -- run as `python repro.py` from a directory ABOVE this file,
# e.g.:
#   mkdir -p repo_root/app_dir && cd repo_root
#   (place this file at repo_root/app_dir/repro.py)
#   python app_dir/repro.py
from dash import Dash, html

app = Dash(__name__, backend="fastapi")
app.layout = html.Div("hello")

if __name__ == "__main__":
    app.run(
        host="127.0.0.1",
        port=8050,
        debug=True,
        reload_dirs=["app_dir"],
        reload_excludes=["app_dir/tests/*"],
    )
  • Expected: the spawned uvicorn --reload subprocess only watches app_dir/, excluding app_dir/tests/*.
  • Actual: reload_dirs/reload_excludes are silently ignored. The subprocess inherits the parent's cwd (repo_root/) and uvicorn defaults reload_dirs to [Path.cwd()], so it watches repo_root/ recursively -- including repo_root/.venv if one exists there.

Root cause

dash/backends/_fastapi.py, FastAPIBackend.run() (dash 4.4.1):

def run(self, dash_app: Dash, host, port, debug, **kwargs):
    ...
    uvicorn_args = [
        sys.executable, "-m", "uvicorn", app_path,
        "--host", str(host), "--port", str(port),
    ]
    if kwargs.get("reload"):
        uvicorn_args.append("--reload")

    dev_tools = dash_app._dev_tools
    config = dict(
        {"debug": debug} if debug else {"debug": False},
        **{f"dev_tools_{k}": v for k, v in dev_tools.items()},
    )
    env = os.environ.copy()
    env[_ENV_CONFIG] = json.dumps(config)

    # Add any other kwargs as CLI args if needed

    proc = subprocess.Popen(uvicorn_args, env=env)
    proc.wait()

Only kwargs["reload"] is ever consulted. reload_dirs, reload_excludes, reload_includes (and anything else a caller passes through app.run(...)) reach this function but are never translated into --reload-dir / --reload-exclude / --reload-include CLI args for the child process.

Suggested fix

Forward at least the reload-scoping kwargs onto uvicorn_args, e.g.:

for d in kwargs.get("reload_dirs") or []:
    uvicorn_args += ["--reload-dir", str(d)]
for p in kwargs.get("reload_excludes") or []:
    uvicorn_args += ["--reload-exclude", str(p)]
for p in kwargs.get("reload_includes") or []:
    uvicorn_args += ["--reload-include", str(p)]

Since this is silent today (no error, no warning), a caller has no way to discover the gap short of reading this source file directly. At minimum, forwarding these three would close the gap for the common case; more generally it might be worth warning on any kwarg that isn't recognized/forwarded here.

Environment

  • dash 4.4.1 (dash[fastapi], backend="fastapi")
  • uvicorn 0.52.0
  • Windows 11, Python 3.11 (the affected code path is not inside a platform-specific branch, so this should reproduce on any OS)

Related

Possibly adjacent to #3818 / #3912 (uvicorn --reload subprocess handling in the FastAPI backend also has callback double-registration issues there), but this is a distinct symptom -- silently dropped reload-scoping kwargs / overly broad default watch scope, not callback duplication.

Ngôn ngữ chính
Python
Star
24.4k
Fork
2.3k
Merge trung bình
1 ngày 19 giờ
Pull request đã merge (30 ngày)
19

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của plotly/dash

Tất cả issue của plotly/dash

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.