Skip to content

fix: use importlib to avoid torchaudio local variable scoping bug#1243

Open
POWERFULMOVES wants to merge 2 commits intofishaudio:mainfrom
POWERFULMOVES:fix/torchaudio-import-scoping
Open

fix: use importlib to avoid torchaudio local variable scoping bug#1243
POWERFULMOVES wants to merge 2 commits intofishaudio:mainfrom
POWERFULMOVES:fix/torchaudio-import-scoping

Conversation

@POWERFULMOVES
Copy link
Copy Markdown

Summary

  • import torchaudio.io._load_audio_fileobj in ReferenceLoader.__init__ creates a local torchaudio binding that shadows the module-level global for the entire method
  • Python determines variable scope at compile time, so line 39 (torchaudio.list_audio_backends()) tries to access the unbound local instead of the module global
  • This manifests as local variable 'torchaudio' referenced before assignment when the module is loaded in contexts that swap sys.modules (e.g., multi-engine TTS frameworks)

Fix

Replace import torchaudio.io._load_audio_fileobj with importlib.import_module('torchaudio.io._load_audio_fileobj') which achieves the same effect without creating a local name binding.

Test plan

  • Verified Fish Speech S2 Pro loads and synthesizes successfully after fix
  • Tested in Ultimate-TTS-Studio (14-engine framework with S1/S2 module isolation)
  • torchaudio 2.7.0+cu128, Python 3.11, CUDA 12.8

Generated with Claude Code

hunnibear and others added 2 commits March 24, 2026 15:44
`import torchaudio.io._load_audio_fileobj` inside ReferenceLoader.__init__
creates a local `torchaudio` binding that shadows the module-level global
for the entire method (Python determines variable scope at compile time).

When this code runs inside an embedding context that swaps sys.modules
(e.g., Ultimate-TTS-Studio's S1/S2 module isolation), line 39's
`torchaudio.list_audio_backends()` fails with:
  "local variable 'torchaudio' referenced before assignment"

Fix: use `importlib.import_module()` which doesn't create local bindings.
@gtherond gtherond mentioned this pull request Mar 25, 2026
6 tasks
Copy link
Copy Markdown
Contributor

@JiwaniZakir JiwaniZakir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix correctly addresses a real Python scoping gotcha — import torchaudio.io._load_audio_fileobj inside a function body binds torchaudio as a local name, which can shadow the module-level import for any subsequent use of torchaudio within __init__. Using importlib.import_module sidesteps this cleanly.

However, import importlib is placed inside the try block in reference_loader.py, which is unnecessary and slightly misleading. Since importlib is a Python standard library module that is always available, it belongs at the top of the file with the other imports rather than being re-imported conditionally on every call. As written, it's also technically inside the except (ImportError, ModuleNotFoundError) guard, meaning if something went wrong with the importlib import itself (contrived, but possible in unusual environments), it would silently fall through to self.backend = "soundfile" rather than raising.

It's also worth verifying whether any other import torchaudio.* submodule statements exist elsewhere in this file or the broader codebase that could trigger the same scoping issue — a single fix here doesn't preclude the same bug being latent in other locations.

@spike4379
Copy link
Copy Markdown

@pre-commit-ci
[[pre-commit.ci] auto fixes from pre-commit.com hooks](/fishaudio/fish-speech/pull/1243/commits/f7527bcab7a0509833d67fcc43fe388aecd1e977)
[f7527bc](/fishaudio/fish-speech/pull/1243/commits/f7527bcab7a0509833d67fcc43fe388aecd1e977)

I noticed you forked this and may have fixed it however I get the same error.

Traceback (most recent call last):
File "F:\ChatGPT\fish-speech\tools\run_webui.py", line 77, in
inference_engine = TTSInferenceEngine(
^^^^^^^^^^^^^^^^^^^
File "F:\ChatGPT\fish-speech\fish_speech\inference_engine_init_.py", line 32, in init
super().init()
File "F:\ChatGPT\fish-speech\fish_speech\inference_engine\reference_loader.py", line 39, in init
backends = torchaudio.list_audio_backends()
^^^^^^^^^^
UnboundLocalError: cannot access local variable 'torchaudio' where it is not associated with a value

Is there any solution to this? Using windows I used the UV sync

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants