上一节已经大体实现了界面,两个输入框,一个按钮,当然还有两个文本标签。
另外我找到了两个免费的天气预报接口
通过城市名字获得天气数据(json)
http://wthrcdn.etouch.cn/weather_mini?city=北京市通过城市ID获得天气数据(json)
http://wthrcdn.etouch.cn/weather_mini?citykey=101010100
这两个接口返回的数据是 Json 格式,希望你没有忘记。在这些 Json 数据里,就有天气数据,还是四五天的预报,真洋气!感谢接口的提供者!
今天我们一鼓作气,将 Json 数据和视窗程序整合在一起,完成第一个有用的作品。
用 Python 访问网络
你也可以在线运行 requests 实例代码
https://repl.it/@alvendarthy/testRequests
如果对天气预报程序稍作剖析,
- 它的界面运行在用户这里,也就是我们自己的电脑上,未来分发给朋友们,就会有很多用户。
- 界面中的数据,城市来自用户输入,天气数据却来自网络。
天气预报小程序的工作场景看起来会是这样:
- 用户的电脑称为客户端(Client),
- 接口服务器称为服务端(Server)
当你听到别人说,我的服务是 C/S 架构的,说的就是这样的情况。
从用户的电脑到别人的服务器(提供网络接口服务的机器,本质上也是电脑)之间的网络连接,实际情况会比较复杂。借助第三方库 requests,可以简化为上图中的样子。
快速看一下用 requests 库怎样获得网络数据:
# 首先当然是 import
import requests
# 使用 requests 的 get 函数,
# 第一个参数是要访问的 url,这里填写接口的完整连接就可以了,我使用了第一个接口
r = requests.get("http://wthrcdn.etouch.cn/weather_mini?city=北京市")
# 接口的数据在这里
print(r.text, type(r.text))
下面是我运行的结果
如果将命令行中第一部分数据(不包含
如何将 Json 格式的字符串转换为 Python 字典呢?还是要用第三方库 json。继续增加代码:
import requests
# 继续导入
import json
# 使用 requests 的 get 函数,
# 第一个参数是要访问的 url,这里填写接口的完整连接就可以了,我使用了第一个接口
r = requests.get("http://wthrcdn.etouch.cn/weather_mini?city=北京市")
# 接口的数据在这里
print(r.text, type(r.text))
# result 是一个 Python 字典
result = json.loads(r.text)
print("result type:", type(result))
print("tomorrw: ", result["data"]["forecast"][0]["type"])
这里用 json.loads(result) 将 r.text 转换为字典:dict 类型,我已经在图中标出。
可以看到通过 result["data"]["forecast"][0]["type"] 就得到了明天的天气,注意 result 嵌套多层,混合了字典和 list。
既然已经可以得到明天的天气了,不如写成函数方便一些。这个函数只接收一个 String 参数:city,就可以了。
import requests
import json
def get_weather(city):
r = requests.get("http://wthrcdn.etouch.cn/weather_mini?city=" + city)
result = json.loads(r.text)
return result["data"]["forecast"][0]["type"]
Tips:
这样的函数可能正常工作,也可能异常,生产环境需要处理各种异常情况,确保逻辑严密。
使用 Windows 系统蓝屏的时候,用户会一边重启,以便诅咒开发者。
所以你懂得,对用户好一点。
异常处理是单独的 Python 话题,你可以在 “菜鸟教程” 和百度上获得更多资料。
合体!
你也可以在这里在线运行合体以后的代码
https://repl.it/@alvendarthy/PySimpleGUIDemo3
不要忘记导入所有需要用的库: PySimpleGUI、requests、json,把我们写好的获取天气的函数也添加进来。
TIPS:
在线环境不支持中文,所以我使用了城市编号接口,在输入窗要输入城市编号,北京的编码是 101010100,其他城市可以在这里查找:
http://mat1.gtimg.com/weather/index2014/wtData_v2.js
你在本地开发的话,就可以将 get_weather 函数中的 url 换成城市名称的接口,方便一些。
import PySimpleGUI as sg
import requests
import json
def get_weather(city):
# 在线环境不支持中文输入,所以我改用城市编号的接口,如果你在电脑上开发,就不受影响
r = requests.get("http://wthrcdn.etouch.cn/weather_mini?citykey=" + city)
result = json.loads(r.text)
return result["data"]["forecast"][0]["type"]
# 让所有文本居中
sg.SetOptions(text_justification='center')
layout = [
[ sg.Text("City", size = (20, 1)), sg.Input(key = "-CITY-") ],
[ sg.Text("Weather", size = (20, 1)), sg.Input(key = "-WEATHER-") ],
[ sg.Button("Submit")]
]
window = sg.Window("Weather App", layout)
event, values = window.read()
print(event, values)
# values 是一个字典,访问可输入组件的 key(定义蓝图时指定了这个参数)可以获得组件的输入
city = values["-CITY-"]
weather = get_weather(city)
print(weather)
window.close()
点击 run,在 city 一栏输入北京的城市编码 101010100, 点击 submit 按钮。
看,已经成功得到天气了。下面,我们让天气显示到 Weather 窗口中。
可输入组件除了可以接受用户的输入外,也可以用代码控制,需要用到 Input 类的 update 方法,它的参数就是输入框中要展现的字符串,当然就是天气字符串了。
TIPS:
你猜怎么清空输入框? 说出来你都不信,update 的参数填写空字符串 “” 就好了!
就剩最后一步了,加油! 下面我们将天气更新到天气框中。之前我们讲过,视窗里的所有组件,都是在蓝图的 list 中定义的,突然要用到 Input 对象,怎么找到它呢?你当然可以通过 layout[1][1] 这样去访问,有更优雅的做法:
window["-INPUT-"]
超简单不是么!这个特性对版本有要求,如果提示错误,你可以选择升级 PySimpleGUI 或者使用经典方法:
- window.Element("-INPUT-")
- window.FindElement("-INPUT-")
它们都是等效的。用这种方法的好处是,当你修改蓝图的时候,只要组件的 key 唯一,你就不需要修改其他代码。
import PySimpleGUI as sg
import requests
import json
def get_weather(city):
# 在线环境不支持中文输入,所以我改用城市编号的接口,如果你在电脑上开发,就不受影响
r = requests.get("http://wthrcdn.etouch.cn/weather_mini?citykey=" + city)
result = json.loads(r.text)
return result["data"]["forecast"][0]["type"]
# 让所有文本居中
sg.SetOptions(text_justification='center')
layout = [
[ sg.Text("City", size = (20, 1)), sg.Input(key = "-CITY-") ],
[ sg.Text("Weather", size = (20, 1)), sg.Input(key = "-WEATHER-") ],
[ sg.Button("Submit")]
]
window = sg.Window("Weather App", layout)
event, values = window.read()
print(event, values)
# values 是一个字典,访问可输入组件的 key(定义蓝图时指定了这个参数)可以获得组件的输入
city = values["-CITY-"]
weather = get_weather(city)
print(weather)
# 找到天气输入框
weather_wind = window["-WEATHER-"]
# 将天气更新到输入框
weather_wind.update(weather)
# 如果没有这一行,程序会一闪而退,你根本看不到效果
window.read()
window.close()
天气一栏,就是 “晴” 了,如果你在本地就一定不会有这样的问题!
太棒了!
学以致用,今天已经开发了一个实际的小工具。别看它功能简单,在此基础上继续添砖加瓦,总会变成理想的那个样子。
明天我们回过头在看一下 PySimpleGUI,了解更多它的细节。