datawhalechina/hello-agents · warning · ValueError
单位必须是 'metric' 或 'imperial'
Error message
单位必须是 'metric' 或 'imperial'
What it means
ValueError raised by WeatherClient.set_unit when the unit argument is not exactly 'metric' or 'imperial'. The unit is passed straight into the OpenWeather 'units' query parameter, and the API only accepts those two literals ('standard' would also be valid for OpenWeather but is deliberately excluded here). Case matters: 'Metric' or 'METRIC' raise.
Source
Thrown at Co-creation-projects/allen2000-FashionDailyDress/weather.py:136
:return: 格式化后的天气信息字符串
"""
weather_data = self._parse_weather_data(data)
return (
f"🏙️ 城市: {weather_data['city']}\n"
f"🌡️ 温度: {weather_data['temperature']}{weather_data['temperature_unit']}\n"
f"📝 天气: {weather_data['description']}\n"
f"💧 湿度: {weather_data['humidity']}%\n"
f"🌬️ 风速: {weather_data['wind_speed']} {weather_data['wind_unit']}"
)
def set_unit(self, unit):
"""
设置温度单位
:param unit: 温度单位(metric=摄氏,imperial=华氏)
"""
if unit not in ['metric', 'imperial']:
raise ValueError("单位必须是 'metric' 或 'imperial'")
self.unit = unit
def set_api_key(self, api_key):
"""
设置API密钥
:param api_key: 新的API密钥
"""
self.api_key = api_key
def get_weather(city_name, api_key=os.environ.get("OPENWEATHER_API_KEY"), unit='metric'):
"""
向后兼容的函数,使用Weather类实现
:param city_name: 城市名称(英文)
:param api_key: 你的OpenWeatherMap API密钥
:param unit: 温度单位(metric=摄氏,imperial=华氏)
:return: 格式化后的天气信息
"""View on GitHub (pinned to 606a07d341)
Solutions
- Normalize before validating: unit = unit.strip().lower() and map synonyms ('c','celsius','℃' -> 'metric'; 'f','fahrenheit','℉' -> 'imperial')
- Use a Literal/Enum at the boundary so invalid values are rejected with a clear message earlier
- If 'standard' (Kelvin) should be supported, add it to the allowed set and update the display logic at line 107 which currently assumes a metric/imperial binary
Example fix
# before
def set_unit(self, unit):
if unit not in ['metric', 'imperial']:
raise ValueError("单位必须是 'metric' 或 'imperial'")
self.unit = unit
# after
_UNIT_ALIASES = {
'metric': 'metric', 'c': 'metric', 'celsius': 'metric', '℃': 'metric',
'imperial': 'imperial', 'f': 'imperial', 'fahrenheit': 'imperial', '℉': 'imperial',
}
def set_unit(self, unit):
unit = _UNIT_ALIASES.get(str(unit).strip().lower())
if unit is None:
raise ValueError(
"单位必须是 'metric' 或 'imperial'(接受别名 c/celsius/f/fahrenheit)"
)
self.unit = unit Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_UNITS = ('metric', 'imperial')
def normalize_unit(unit: str) -> str | None:
u = str(unit).strip().lower()
return u if u in ALLOWED_UNITS else None
unit = normalize_unit(raw)
if unit is None:
# reject / re-prompt before touching the client
... Type guard
from typing import Literal
Unit = Literal['metric', 'imperial']
def is_unit(v) -> bool:
return v in ('metric', 'imperial') Try / catch
try:
client.set_unit(raw_unit)
except ValueError:
client.set_unit('metric') # safe default
notify_user('unrecognized unit, using Celsius') Prevention
- Normalize case and map synonyms (c/celsius/f/fahrenheit) before calling set_unit
- Type the boundary with Literal['metric','imperial'] or an Enum so invalid input is caught earlier
- Validate any LLM- or user-supplied unit string before forwarding it to the weather client
When it happens
Trigger: set_unit('c'), set_unit('C'), set_unit('celsius'), set_unit('standard'), set_unit('Metric') — all raise; user-config or LLM-provided unit strings not normalized before the call; uppercase values from an enum or CLI flag; passing the display symbol '°C'.
Common situations: Dress-recommendation agent letting a user say '摄氏' or 'C' and forwarding it raw; config file storing unit as 'Celsius'; CLI accepting --unit without validation.
Related errors
AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14).
Data as JSON: /api/errors/1dd4af5c6406b156.
Report an issue: GitHub.