Interface編集部
2025年2月号 特集第1部サポートページ
第1部第3章
●お詫びと訂正
リスト3のコマンドについて,オプションの指定が抜けておりました.次の通り訂正いたします.
$ Docker container run -v .:/workspace -e YOUR_NAME=cquser -it python:3.12 python3 /workspace/main.py
第1部第5章 初めてのDocker開発②…アプリケーション実装
ステップ③…サーバ側アプリの作成
■天気情報を扱うサーバ
Open Weather Mapにアクセスして,天気予報を取得するプログラム(weather_info_controller.py)を次に示します.
REST APIは,
https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={API key}
といった形でリクエストします.
ここで緯度経度の情報が必要です.Open Weather Mapで提供されているGeocoding API (https://openweathermap.org/api/geocoding-api)を使って,都市情報から緯度経度をを得るように実装しました.
これが,_get_lat_lon関数の部分です.
エンドポイントの情報やAPIキーについては、環境変数で設定されるものとしています.
import os, requests, json
from datetime import datetime, timedelta
class WeatherInfoController:
def __init__(self):
self._api_key = os.environ[‘OPEN_WEATHER_MAP_API_KEY’]
self._api_endpoint = os.environ[‘OPEN_WEATHER_MAP_ENDPOINT’]
self._current_weather_forecast = [ ]
self._get_lat_lon()
self.fetch_weather_info()
def get_forecast(self) -> list:
return self._current_weather_forecast
def _get_lat_lon(self):
”’国名,都市 の形式で設定された情報から緯度経度を取得する.”’
geo_api_endpoint = os.environ.get(‘OPEN_WEATHER_MAP_GEO_API_ENDPOINT’)
location_info= os.environ.get(‘WEATHER_LOCATION’)
params = {
‘q’: location_info, ‘appid’: self._api_key,
}
response = requests.get(geo_api_endpoint, params)
json_data = response.json()[0] ## 制限事項: 最初のものだけを採用する.
self._geo_coords = { ‘lat’: json_data[‘lat’], ‘lon’: json_data[‘lon’] }
def _convert_weather_id(self, weather_id):
”’weather idから扱いやすい天気名称・強度の組を生成”’
## OpenWeatherMapの天気IDから変換
## https://openweathermap.org/weather-conditions を元に判定.
strength = ‘normal’
weather_keyword = ‘other’
try:
id = int(weather_id)
group_id = int(id / 100)
if group_id == 2: ## 雷
weather_keyword = ‘thunderstorm’
strength = ‘strongly’
if group_id == 3:
weather_keyword = ‘drizzle’ ## 霧
if group_id == 5:
weather_keyword = ‘rain’ ## 雨
if 502 <= id & id <= 504:
strength = ‘strongly’
if group_id == 6:
weather_keyword = ‘snow’ ## 雪
if group_id == 8:
if id <= 801:
weather_keyword = ‘clear’ ## 晴れ(快晴/25%以下の雲)
else:
weather_keyword = ‘clouds’ ## 曇り
return (weather_keyword, strength)
except:
return (‘unknown’, strength)
def fetch_weather_info(self) -> bool:
”’OpenWeatherMapにアクセスして天気予報を取得”’
try:
params = {
‘lat’: self._geo_coords[‘lat’],
‘lon’: self._geo_coords[‘lon’],
‘appid’ : self._api_key,
‘units’: ‘metric’,
‘cnt’: 12
}
response = requests.get(self._api_endpoint, params)
json_data = response.json()
offset = timedelta(seconds=int(json_data[‘city’][‘timezone’]))
entries = [ ]
for item in json_data[‘list’]:
dt = datetime.fromtimestamp(item[‘dt’]).strftime(‘%Y-%m-%d %H:%M:%S’)
##dt_jst = (dt + offset).strftime(‘%Y-%m-%d %H:%M:%S’)
main = item[‘main’]
temperature = main[‘temp’] ## (予想)気温
humidity = main[‘humidity’] ## (予想)湿度
weather_main = item[‘weather’][0][‘main’]
weather_id = item[‘weather’][0][‘id’]
rain_percent = int(float(item.get(‘pop’, 0)) * 100)
weather_keyword, strength = self._convert_weather_id(weather_id)
entries.append({
‘datetime’: dt,
‘temperature’: temperature,
‘humidity’: humidity,
‘weather’: weather_main, ‘weather_id’: weather_id,
‘rain’: rain_percent,
‘weather_keyword’: weather_keyword,
‘strength’ : strength
})
self._current_weather_forecast = entries
except:
return False
return True