Probably just a really annoying library version mismatch…
1. What the error actually means
You are seeing:
ModuleNotFoundError: No module named 'websockets.asyncio'
This is not “websockets is missing”. It means:
- The
websocketspackage is installed, but - It is an older version that doesn’t contain the
websockets.asynciopackage.
The websockets library reorganised itself:
- “New” implementation lives in
websockets.asyncio.*. - “Old” implementation was moved to
websockets.legacy.*and kept for backwards compatibility.
If code tries to do:
from websockets.asyncio.client import connect # or ClientConnection etc.
and the environment has an old websockets (before this layout), Python raises exactly the error you are seeing.
So the fundamental bug is:
Libraries in your Space expect new-style
websockets.asyncio, but the Space actually has oldwebsocketsinstalled.
Everything else is symptoms of that mismatch.
2. How yfinance and Gradio got involved
2.1 yfinance
Recent yfinance releases added WebSocket-based live streaming data (WebSocket and AsyncWebSocket).
Internally, that module imports:
from websockets.asyncio.client import connect as async_connect
and is pulled in when you import yfinance. A GitHub issue shows users hitting exactly your error when they do import yfinance and have an old websockets installed.
So:
yfinance >= 0.2.59+websockets < 13⇒ModuleNotFoundError: websockets.asyncio.
Even if your code never uses live streaming, the import still runs and still fails.
2.2 Gradio / gradio_client
Newer Gradio uses WebSockets internally and its Python client imports:
from websockets.asyncio.client import ClientConnection
The Gradio changelog explicitly mentions a fix:
“fix(client): websockets minimum version for asyncio” in Gradio 5.47.0, raising the minimum
websocketsversion so that theasyncioAPI is present.
Before that fix, there was a bad combination:
gradio-client 1.5.0requiredwebsockets < 13.0.- At the same time, code in the client (and in other libs such as Supabase) imported
websockets.asyncio.client.*.
This combination makes it impossible to satisfy all requirements: the client forces an old websockets that doesn’t have websockets.asyncio, and the code then tries to import websockets.asyncio.
There is a Gradio issue where a user deploying to Hugging Face Spaces suddenly starts getting:
ModuleNotFoundError: No module named 'websockets.asyncio'
just from importing Supabase in a Gradio Space, after everything had worked previously.
That is the same pattern you are seeing.
3. Why it’s so persistent specifically on Hugging Face Spaces
Locally, you can just do:
pip install "gradio>=5.47.0" "yfinance>=0.2.59" "websockets>=13"
and be done.
In a Gradio Space, the installation order is different:
-
The runner installs your
requirements.txt. -
Then it installs the Gradio SDK specified by the
sdk/sdk_versionfields inREADME.md.The Hugging Face docs say:
“The gradio package is pre-installed and its version is set in the
sdk_versionfield in the README.md file.” -
That SDK install pulls in its own
gradio-clientand can override versions you requested inrequirements.txt.
The result:
- Pinning
websocketsinrequirements.txtdoes not guarantee that version in the final container. - Pinning
gradio==3.38.0inrequirements.txtalso does not control the actual Gradio version on a Gradio Space; HF staff explicitly recommend not pinning Gradio inrequirements.txtand usingsdk_versioninstead. - Some Gradio / gradio-client versions used by Spaces still depend on
websockets<13.
There is also a community post showing that the Space base image first runs pip install -r requirements.txt and then later installs other packages (like Gradio and spaces), which can silently change versions again.
This explains your situation:
- You add
websocketstorequirements.txtand pin versions. - During the SDK install step, Spaces installs a Gradio / gradio-client combo that downgrades
websocketsor upgradesyfinancebeyond what you pinned. - Then
import yfinanceorimport gradiohitswebsockets.asynciowith an incompatiblewebsocketsversion and crashes.
So yes, it behaves as a platform-level environment issue: the final dependency stack in the Space is not what your requirements.txt suggests.
4. Diagnosing your Space concretely
Before changing things, you want to see what’s actually installed inside the Space (since requirements.txt is not the final truth).
At the top of app.py, temporarily add:
import sys
print("Python:", sys.version)
def _debug_versions():
import gradio, yfinance, websockets
print("Gradio version:", gradio.__version__)
print("yfinance version:", yfinance.__version__)
print("websockets version:", websockets.__version__)
try:
from websockets.asyncio import client as _c
print("websockets.asyncio IS available")
except Exception as e:
print("websockets.asyncio import FAILED:", repr(e))
_debug_versions()
Then trigger a Factory rebuild and look at the container logs.
You will almost certainly see one of these:
websocketsis<13andwebsockets.asyncio import FAILED, oryfinanceversion is higher than what you pinned (e.g. ≥ 0.2.59 even ifrequirements.txtsays 0.2.28).
That tells you which part of the stack is violating your expectation.
5. Workaround / solution options
There are three practical approaches.
Option A – Modern stack: align everything on websockets>=13 (recommended if you’re comfortable upgrading)
Goal: run new Gradio, new yfinance, and a new websockets that includes websockets.asyncio.
-
Control Gradio via
sdk_version, notrequirements.txt.In
README.md:--- title: DCF-Stock-Final sdk: gradio sdk_version: 5.47.1 # or any ≥ 5.47.0 app_file: app.py python_version: 3.10 ---Gradio 5.47.0 is where they fixed the client to require a sufficiently new websockets for asyncio.
Remove any
gradio==...line fromrequirements.txtfor this Space. -
Pin the other key packages in
requirements.txt.Example:
# yfinance with websocket support (if you want live streaming) yfinance>=0.2.59,<0.3 # Ensure the asyncio API exists websockets>=13,<16 # your other deps (pandas, numpy, etc.)websockets>=13ensures thewebsockets.asynciopackage exists.- yfinance 0.2.59+ is designed to use WebSocket features and assumes a recent websockets.
-
Factory rebuild and re-check the
_debug_versions()output.You want:
- Gradio ≈ 5.47+,
- websockets ≥ 13, and
- “
websockets.asyncio IS available”.
If that’s true, the ModuleNotFoundError: websockets.asyncio should vanish, because:
- Gradio’s client now explicitly requires websockets new enough, and
- yfinance’s
live.pycan importwebsockets.asyncio.client.connectnormally.
Option B – Avoid the WebSocket dependency entirely (older yfinance, older Gradio)
If you do not need yfinance live streaming for your DCF tool (most DCF tools only use historical data), you can sidestep the entire websockets chain.
-
Pin yfinance to a version before the WebSocket module was introduced – for example:
yfinance==0.2.58 # or another pre-WebSocket version you’ve testedA serverless deployment issue notes that 0.2.59 introduced changes that pulled in websockets and caused environment failures; older versions did not.
Those older versions don’t import
websockets.asyncioat all. -
Do not depend on websockets directly in your code or requirements (unless absolutely needed elsewhere).
If nobody imports
websockets.asyncio, it no longer matters whichwebsocketsversion the Space image happens to ship. -
Optionally choose a Gradio
sdk_versionbefore the websockets-asyncio changes ingradio-client, or any current version where you do not use features requiringwebsockets.asyncio. For a simple DCF form, an older but stable Gradio is usually fine.
This is essentially the “stay on the last non-WebSocket yfinance” approach people used on platforms like Azure Functions when the new versions started breaking their environments.
Option C – Docker Space with full control
If you want to completely isolate yourself from HF’s base image and future changes:
-
Convert the Space to Docker SDK (
sdk: docker) in the README and add aDockerfile. -
Minimal Dockerfile:
FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["python", "app.py"] -
In
requirements.txtfor this Docker build, you can now fix everything exactly:gradio==5.47.1 yfinance==0.2.59 websockets>=13,<16 # other deps...
Here the HF platform simply builds your image; it no longer installs its own Gradio SDK afterwards, so you avoid surprise downgrades or conflicts.
6. Short bullet summary
-
The error means: code imports
websockets.asyncio.*but the installedwebsocketsis too old to have that package. -
Newer yfinance and Gradio both rely on
websockets.asyncio. -
HF Gradio Spaces pre-install Gradio based on
sdk_versionand can override versions fromrequirements.txt, including downgradingwebsockets. -
That’s why your Space keeps failing even with seemingly correct pins: the final container doesn’t match
requirements.txt. -
Fixes/workarounds:
- Option A: use a recent Gradio SDK (≥5.47), don’t pin Gradio in requirements, and pin
websockets>=13+ compatible yfinance. - Option B: pin yfinance to a pre-WebSocket version (≤0.2.58) and avoid websockets entirely if you don’t need live streaming.
- Option C: switch to Docker SDK and control all versions yourself.
- Option A: use a recent Gradio SDK (≥5.47), don’t pin Gradio in requirements, and pin
8. Source links (for quick reference)
-
yfinance issue – “No module named
websockets.asynciowhen import yfinance”:
https://github.com/ranaroussi/yfinance/issues/2454 -
yfinance WebSocket docs and PyPI description (live streaming support):
https://ranaroussi.github.io/yfinance/reference/yfinance.websocket.html
https://pypi.org/project/yfinance/ -
Gradio changelog noting “fix(client): websockets minimum version for asyncio” in 5.47.0:
https://www.gradio.app/changelog -
Gradio issue – “No module named ‘websockets.asyncio’ when importing supabase on Hugging Face” (Spaces context):
https://github.com/gradio-app/gradio/issues/10661 -
gradio-client dependency pin –
websockets<13.0discussion:
https://github.com/gradio-app/gradio/issues/10085 -
websockets docs – explanation of new
websockets.asynciovs legacy implementation:
https://websockets.readthedocs.io/en/stable/howto/upgrade.html -
Hugging Face Spaces docs – Gradio Spaces and dependencies:
https://huggingface.co/docs/hub/en/spaces-sdks-gradio
https://huggingface.co/docs/hub/en/spaces-dependencies -
HF forum: “Huggingface spaces not updating packages from requirements.txt” (why you shouldn’t pin Gradio in
requirements.txtin Gradio Spaces):
https://huggingface.co/proxy/discuss.huggingface.co/t/huggingface-spaces-not-updating-packages-from-requirements-txt/92865