|
G A C E T
A D E L I N U X |
|
Estación Meteorológica Python
Por Phil Hughes Traducción al español por José Gregorio Del Sol Cobos
|
Este programa es una simple interfaz que le permite construir una página web a a partir de la salida de los datos Metar de las estaciones meteorológicas de todo el mundo. No lo llamaría excitante, pero funciona.
Mejor que describir lo que usted ve, vaya aquí, y eche un vistazo. Debería ver al menos dos y posiblemente hasta cinco informes meteorológicos desde Costa Rica. O sea, el programa tiene una lista de cinco estaciones meteorológicas para probar y muestra la información de todo ese informe.
El corazón del sistema es el paquete Pymetar, disponible aquí. Éste es el programa en Python que trae los datos Metar descrito aquí. Pymetar es una herramienta en línea de comandos, pero hace todo el trabajo sucio.
Mi objetivo es hacer disponible esta información en una página web. No quería que esto se volviese un gran proyecto de programación, pero sí que la implementación tenga sentido. La aproximación más básica habría sido ejecutar el programa como un guión CGI para cada petición. Sin embargo, esto era potencialmente muy ineficiente porque requeriría que el programa se hiciera con todos los datos cada vez que llegara una petición al CGI. Más importante, significaría que el usuario tendría que esperar a que se completasen todas esas peticiones.
Decidí que el mejor compromiso era instalar un trabajo cron para recopilar los datos y construir una página meteorológica. Entonces, cada petición de una página simplemente estaría mostrando una página estática. Como los datos meteorológicos no cambian tan a menudo, esto efectivamente ofrece información bastante actual.
Lo primero, aquí está el código:
#!/usr/bin/env python
import sys
import time
sys.path.insert(0, "/home/fyl/pymetar-0.5")
import pymetar
def stations(args):
for arg in map(lambda x: x.strip(), args):
try:
weather = pymetar.MetarReport(arg)
except IOError, msg:
# descomentar lo siguiente y quitar el paso de línea para ver los errores
# sys.stderr.write("Problem accessing the weather server: %s\n" % msg)
pass
else:
if weather.valid:
print "<h3>"
print weather.getStationName()
print " ( Lat: %s, Long: %s, Alt: %s m)" % \
weather.getStationPosition()
print "</h3>"
print "<table border=\"2\">"
print "<tr><td>Updated</td><td> %s</td></tr>" % \
weather.getTime()
if weather.getWindDirection() is not None:
print "<tr><td>Wind direction</td><td> %s°</td></tr>" % \
weather.getWindDirection()
if weather.getWindSpeed() is not None:
print "<tr><td>Wind speed</td><td> %6.1f m/s</td></tr>" % \
weather.getWindSpeed()
if weather.getTemperatureCelsius() is not None:
print "<tr><td>Temperature</td><td> %.1f°C (%.1f°F)</td></tr>" % \
(weather.getTemperatureCelsius(), \
weather.getTemperatureFahrenheit())
if weather.getDewPointCelsius() is not None:
print "<tr><td>Dew point</td><td> %.1f°C (%.1f°F)</td></tr>" % \
(weather.getDewPointCelsius(), \
weather.getDewPointFahrenheit())
if weather.getHumidity() is not None:
print "<tr><td>Humidity</td><td> %.0f%%</td></tr>" % \
weather.getHumidity()
if weather.getVisibilityKilometers() is not None:
print "<tr><td>Visibility</td><td> %.1f Km</td></tr>" % \
weather.getVisibilityKilometers()
if weather.getPressure() is not None:
print "<tr><td>Pressure</td><td> %.0f hPa</td></tr>" % \
weather.getPressure()
if weather.getWeather() is not None:
print "<tr><td>Weather</td><td> %s</td></tr>" % \
weather.getWeather()
if weather.getSkyConditions() is not None:
print "<tr><td>Sky conditions</td><td> %s</td></tr>" % \
weather.getSkyConditions()
print "</table>"
else:
print "Either %s is not a valid station ID, " % arg
print "the NOAA server is down or parsing is severely broken."
print "<html>"
print "<head>"
print "<title>Costa Rica weather from PlazaCR.com</title>"
print "</head>"
print "<body>"
print "<h1>Costa Rica weather from PlazaCR.com</h1>"
print "<p>Latest reports as of %s CST" % time.ctime()
gm = time.gmtime()
print "(%d.%02d.%02d %02d%02d UTC)" % (gm[0], gm[1], gm[2], gm[3], gm[4])
print '<p><a href="images/costa_rica.gif" target="_blank">Costa Rica map</a>'
stations(["MROC", "MRLM", "MRCH", "MRLB", "MRPV"])
print "</body>"
print "</html>"
Nota del traductor: dado que el código es material del autor, he dejado en inglés lo que después se convierte ne la salida del programa
Elijo importar simplemente el código pymetar.py en la envoltura que genera la página HTML. Para esto, añadí el directorio de Pymetar a la ruta que sigue Python para buscar.
Seguido defino stations, una función que consulta las estaciones meteorológicas empleando el código de Pymetar y después formatea la salida en HTML. Parece muy fea porque consiste sólo en largas sentencias print que construyen las cadenas HTML con algunas sentencias para ver si efectivamente se obtienen los datos. El punto importante es que le pasas una lista de nombres de estaciones y obtiene a la vuelta el cuerpo de la página web.
Finalmente, las últimas puede que 15 líneas de código simplemente construyen el recipiente HTML y llaman a las estaciones para producir,
Debido al diseño, el testado es muy sencillo. No hay dependencias basadas en web en el diseño, de modo que simplemente puede ejecutar el programa desde la línea de comandos.
En mi caso, llamé al programa wcr, de modo que simplemente escribiendo ./wcr ejecutará el programa y mostrará el HTML en la salida habitual. Si todo va bien, ejecute de nuevo el programa, redirigiendo la salida a un fichero. Por ejemplo,
./wcr > /tmp/weather.html
Ahora usted puede apuntar un navegador web hacia el fichero y ver si visualiza la página que usted quiere. Si no, es el momento de hacer cambios en wcr y seguir testando.
Una vez que usted está contento con la salida, suba el código a su servidor web y prepare un trabajo cron para ejecutarlo. Normalmente, crontab -e le permitirá editar su entrada crontab.
Yo elegí ejecutar el programa dos veces cada hora, a y cinco y a menos veinticinco. La entrada crontab debe ejecutar el programa y escribir el fichero de salida en una localización que pueda conocer el servidor web. Yo usé:
5,35 * * * * /home/fyl/pymetar-0.5/bin/wcr > /var/www/htdocs/weather.html
Los cuatro asteriscos le dicen a cron que 5 y 35 minutos se aplican a cada hora de cada día. El siguiente campo es el nombre del programa a ejecutar. Finalmente, el operador de redirección (>) es seguido por el lugar donde se ha de almacenar el archivo HTML.
Asumiendo que pone todos los permisos bien, o sea, que el programa puede escribir el fichero y el servidor web puede leerlo, ya está todo. Simplemente apunte a ese fichero, y ya tiene una página meteorológica.
Para el perfeccionista, probablemente necesita una solución más elegante. ¿por qué? Bueno, hay un momento en el cual los contenidos del documento HTML no serán válidos. Cuando cron empieza la tarea, los contenidos de la salida se truncan. Entonces el programa se ejecuta y construye un nuevo fichero.
Debido a cómo trabajar el programa esta vez no es simplemente una ejecución corta de algo de código en Python según el programa consulta las diversas estaciones meteorológicas y tiene que esperar a la respuesta. Con las cinco estaciones que encuesté, vi tiempos transcurridos de entre uno y diez segundos. Si tener malos datos durante un máximo de 10 segundos cada 30 minutos es aceptable para usted, todo está bien. Si no, escriba la salida en un fichero temporal y entonces muévalo al fichero de verdad cuando todo esté completo. Aún no es perfecto, pero se acerca mucho.
Ahora, para nosotros los mortales, tenemos una bonita página meteorológica. Que se divierta.
Phil Hughes es el editor de Linux Journal. y por tanto de Linux Gazette. Sueña permanentemente con la teleconmutación desde su casa en la costa del Pacífico de la Península Olympic. Como empleador, él es "Vicioso, Malo, Tacaño, & Desagradable", pero agradable" como un jefe debe ser.