Skip to content

Commit eb27470

Browse files
committed
🔧 fix(model): enhance Windows model loading with robust path handling
- Improve model loading strategies for Windows compatibility - Add multiple fallback mechanisms for loading models with special characters - Enhance error logging and temporary file management - Optimize path resolution and loading attempts
1 parent 4fffd3a commit eb27470

File tree

2 files changed

+58
-21
lines changed

2 files changed

+58
-21
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "fast-langdetect"
3-
version = "0.3.0"
3+
version = "0.3.1"
44
description = "Quickly detect text language and segment language"
55
authors = [
66
{ name = "sudoskys", email = "[email protected]" },

src/fast_langdetect/infer.py

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -130,30 +130,67 @@ def load_with_download(self, model_path: Path, proxy: Optional[str] = None) -> A
130130
return self.load_local(model_path)
131131

132132
def _load_windows_compatible(self, model_path: Path) -> Any:
133-
"""Handle Windows path compatibility issues."""
134-
if re.match(r'^[A-Za-z0-9_/\\:.]*$', str(model_path)):
135-
return fasttext.load_model(str(model_path))
133+
"""
134+
Handle Windows path compatibility issues when loading FastText models.
136135
137-
# Create a temporary file to handle special characters in the path
138-
with tempfile.NamedTemporaryFile(delete=False) as tmp:
139-
tmp_path = tmp.name
140-
shutil.copy2(model_path, tmp_path)
136+
Attempts multiple strategies in order:
137+
1. Direct loading if path contains only safe characters
138+
2. Loading via relative path if possible
139+
3. Copying to temporary file as last resort
140+
141+
:param model_path: Path to the model file
142+
:return: Loaded FastText model
143+
:raises DetectError: If all loading strategies fail
144+
"""
145+
model_path_str = str(model_path.resolve())
146+
147+
# 策略1: 直接加载安全路径
148+
if re.match(r'^[A-Za-z0-9_/\\:.\-]*$', model_path_str):
149+
try:
150+
return fasttext.load_model(model_path_str)
151+
except Exception as e:
152+
logger.debug(f"fast-langdetect: Direct loading failed: {e}")
141153

154+
# 策略2: 尝试使用相对路径
142155
try:
143-
model = fasttext.load_model(tmp_path)
144-
return model
156+
cwd = Path.cwd().resolve()
157+
# 检查模型路径是否在当前工作目录下
158+
if str(model_path).startswith(str(cwd)) or model_path_str.upper().startswith(str(cwd).upper()):
159+
rel_path = os.path.relpath(model_path, cwd)
160+
if re.match(r'^[A-Za-z0-9_/\\:.\-]*$', rel_path):
161+
return fasttext.load_model(rel_path)
162+
except Exception as e:
163+
logger.debug(f"fast-langdetect: Relative path loading failed: {e}")
164+
165+
# 策略3: 使用临时文件作为最后手段
166+
logger.debug(f"fast-langdetect: Using temporary file for model: {model_path}")
167+
tmp_path = None
168+
try:
169+
with tempfile.NamedTemporaryFile(delete=False) as tmp:
170+
tmp_path = tmp.name
171+
172+
shutil.copy2(model_path, tmp_path)
173+
return fasttext.load_model(tmp_path)
174+
except Exception as e:
175+
if tmp_path and os.path.exists(tmp_path):
176+
try:
177+
os.unlink(tmp_path)
178+
except:
179+
pass
180+
raise DetectError(f"Failed to load model via temporary file: {e}")
145181
finally:
146-
try:
147-
os.unlink(tmp_path)
148-
except (OSError, PermissionError) as e:
149-
logger.warning(f"fast-langdetect: Failed to delete temporary file {tmp_path}: {e}")
150-
# Schedule file for deletion on next reboot on Windows
151-
if platform.system() == "Windows":
152-
try:
153-
import _winapi
154-
_winapi.MoveFileEx(tmp_path, None, _winapi.MOVEFILE_DELAY_UNTIL_REBOOT)
155-
except (ImportError, AttributeError, OSError) as we:
156-
logger.warning(f"fast-langdetect: Failed to schedule file deletion: {we}")
182+
if tmp_path and os.path.exists(tmp_path):
183+
try:
184+
os.unlink(tmp_path)
185+
except (OSError, PermissionError) as e:
186+
logger.warning(f"fast-langdetect: Failed to delete temporary file {tmp_path}: {e}")
187+
# 在Windows上计划在下次重启时删除
188+
if platform.system() == "Windows":
189+
try:
190+
import _winapi
191+
_winapi.MoveFileEx(tmp_path, None, _winapi.MOVEFILE_DELAY_UNTIL_REBOOT)
192+
except (ImportError, AttributeError, OSError) as we:
193+
logger.warning(f"fast-langdetect: Failed to schedule file deletion: {we}")
157194

158195
def _load_unix(self, model_path: Path) -> Any:
159196
"""Load model on Unix-like systems."""

0 commit comments

Comments
 (0)