一个汇率换算工具

自己用python写的一个汇率小工具

汇率转换器

​ 学习Python的过程中想使用Python写一些小的工具来练习,这次写了一个汇率转换器。

界面

1

通过下拉列表选择基准货币,以及想要兑换的目的货币,使用Demand按钮查询汇率,在Number of Money 处输入想要兑换的货币数量,Exchange按钮进行转换,push将数据存入数据库,Quit进行退出。

过程

​ 最初写了一个简单的换算脚本,后来通过API接口的方式在线查询实时汇率,然后加入GUI界面进行包装,最后实现将查询的数据存入数据库

实现

​ 介绍一些实现过程的细节以及遇到的问题。

实时汇率查询

​ 通过已经定制好的API接口直接进行查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def request1(appkey, num1, m="GET"):
url = "http://web.juhe.cn:8080/finance/exchange/rmbquot"
params = {
"key": appkey, # APP Key
"type": "", # 两种格式(0或者1,默认为0)
}

params = urlencode(params)
if m == "GET":
f = urllib.request.urlopen("%s?%s" % (url, params))
else:
f = urllib.request.urlopen(url, params)

content = f.read()
res = json.loads(content)
if res:
error_code = res["error_code"]
if error_code == 0:
# 成功请求
# %s %f %d
#print("%s的汇率为:%f" % (res["result"][0]['data' + num1]['name'], float(res["result"][0]['data' + num1]['fBuyPri']) * 0.01))
return float(res["result"][0]['data' + num1]['fBuyPri']) * 0.01, res["result"][0]['data' + num1]['name']
else:
print("%s:%s" % (res["error_code"], res["reason"]))
else:
print("request api error")

​ 其中appkey参数是我们在网站上申请的key,查询的函数主要用了urllib库中的一些知识,urllib.request.urlopen()函数用于实现对目标url的访问。

urlopen()函数原型如下:

urllib.request.urlopen(url, data=None, [timeout, ]*,cafile=None,capath=None,cadefault=False,context=None)

​ 利用json.loads函数,将字符串转化为字典,这里需要注意的是读取json的数据时,因为后面的数组中不同的货币美元、英镑、港币等分别存放在不同的datex(data1,data2……)中,所以这里选择进行拼接[‘data’ + num1],其中num1是用户选择的货币在

currency = ["人民币","美元","欧元","港币","日元","英镑","澳大利亚元"]字典中的位置

GUI界面

​ 使用tkinter库进行了简单的GUI搭建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def makeform(root,fields):
entries ={}
entries1 ={}
for field in fields:
row = Frame(root) #Frame就是屏幕上的一块矩形区域,多是用来作为容器(container)来布局窗体。
#文本或图像在背景内容区的位置:anchor
# 可选值为(n,s,w,e,ne,nw,sw,se,center)
# eswn是东南西北英文的首字母,表示:上北下南左西右东
lab = Label(row,width = 22,text = field + ":",anchor = 'w')
com = ttk.Combobox(row, state='readonly')
com['values'] = (currency)
com.current(0) #添加默认值为0
row.pack(side = TOP,fill = X,padx = 5,pady =5)
lab.pack(side = LEFT)
com.pack(side = RIGHT,expand = YES,fill =X)
entries[field] = com

for field1 in fields1:
row1 =Frame(root)
lab = Label(row1, width=22, text=field1 + ": ", anchor='w')
ent = Entry(row1)
ent.insert(0, "0")
row1.pack(side = TOP,fill = X,padx = 5,pady =5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries1[field1] = ent

return entries,entries1

​ 第一个for循环用于创建基准货币和交换货币的显示窗口和下拉列表,第二个for循环用于创建货币数量、汇率、交换结果、存入数据库结果的显示窗口和输入框。因为想在基准货币和交换货币内实现下拉列表的形式,所以分成了两个for循环

entries[field] = com entries1[field1] = ent分别存入两个字典,并返回可以在后面方便调用。

查询,转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def exchange(entries1): #转换
num = float(entries1['Number of Money'].get())
rate = float(entries1['Rate'].get())
result = num * rate
entries1['Result'].delete(0, END)
entries1['Result'].insert(0,result)

def demand(entries,entries1): #查询
str1 = currency.index(entries['Basic Money'].get())
str2 = currency.index(entries['Exchange Money'].get())
if (int(str1) != 0):
basic_price, basic_name = request1(appkey, str(str1), "GET")
else:
basic_price, basic_name = 1, "人民币"
if (int(str2) != 0):
exchange_price, exchange_name = request1(appkey, str(str2), "GET")
else:
exchange_price, exchange_name = 1, "人民币"
rate = basic_price/exchange_price
entries1['Rate'].delete('0',END)
entries1['Rate'].insert('0',round(rate,4))`

​ 查询和转换功能需要强调的就是提取下拉列表和输入框内容的部分,我们在生成GUI时,将下拉列表和输入框都存入了字典,这样在使用其数据时,只需要使用

entries[‘Basic Money’].get()

这样的方法

同样想将生成的数据填入空白框内

entries1[‘Rate’].delete(‘0’,END) entries1[‘Rate’].insert(‘0’,round(rate,4))

数据库模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def put_mysql(entries,entries1):
db = pymysql.connect("localhost","root","123456","exchange_money",charset="utf8")
cursor = db.cursor()
sql = "INSERT INTO EMPLOYEE(BASIC_MONEY,EXCHANGE_MONEY,ECHANGE_RATE,NUMBER) values (%s,%s,%s,%s)"
try:
cursor.execute(sql,[entries['Basic Money'].get(),entries['Exchange Money'].get(),
entries1['Rate'].get(),entries1['Number of Money'].get()])
db.commit()
entries1['Database'].delete(0,END)
entries1['Database'].insert(0,'数据已入库')
except Exception as e:
print("error:%s" %e)
db.rollback()
print("存入失败")

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import pymysql
from urllib.parse import urlencode

fields =('Basic Money','Exchange Money')
fields1 = ('Number of Money','Rate','Result','Database')
currency = ["人民币","美元","欧元","港币","日元","英镑","澳大利亚元"]
appkey = "cbea01f970765eabe53f4eb73422fdf8"

def put_mysql(entries,entries1):
db = pymysql.connect("localhost","root","123456","exchange_money",charset="utf8")
cursor = db.cursor()
sql = "INSERT INTO EMPLOYEE(BASIC_MONEY,EXCHANGE_MONEY,ECHANGE_RATE,NUMBER) values (%s,%s,%s,%s)"
try:
cursor.execute(sql,[entries['Basic Money'].get(),entries['Exchange Money'].get(),
entries1['Rate'].get(),entries1['Number of Money'].get()])
db.commit()
entries1['Database'].delete(0,END)
entries1['Database'].insert(0,'数据已入库')
except Exception as e:
print("error:%s" %e)
db.rollback()
print("存入失败")

db.close()
def exchange(entries1): #转换
num = float(entries1['Number of Money'].get())
rate = float(entries1['Rate'].get())
result = num * rate
entries1['Result'].delete(0, END)
entries1['Result'].insert(0,result)

def demand(entries,entries1): #查询
str1 = currency.index(entries['Basic Money'].get())
str2 = currency.index(entries['Exchange Money'].get())
if (int(str1) != 0):
basic_price, basic_name = request1(appkey, str(str1), "GET")
else:
basic_price, basic_name = 1, "人民币"
if (int(str2) != 0):
exchange_price, exchange_name = request1(appkey, str(str2), "GET")
else:
exchange_price, exchange_name = 1, "人民币"
rate = basic_price/exchange_price
entries1['Rate'].delete('0',END)
entries1['Rate'].insert('0',round(rate,4))

def request1(appkey, num1, m="GET"):
url = "http://web.juhe.cn:8080/finance/exchange/rmbquot"
params = {
"key": appkey, # APP Key
"type": "", # 两种格式(0或者1,默认为0)
}

params = urlencode(params)
if m == "GET":
f = urllib.request.urlopen("%s?%s" % (url, params))
else:
f = urllib.request.urlopen(url, params)

content = f.read()
res = json.loads(content)
if res:
error_code = res["error_code"]
if error_code == 0:
# 成功请求
# %s %f %d
#print("%s的汇率为:%f" % (res["result"][0]['data' + num1]['name'], float(res["result"][0]['data' + num1]['fBuyPri']) * 0.01))
return float(res["result"][0]['data' + num1]['fBuyPri']) * 0.01, res["result"][0]['data' + num1]['name']
else:
print("%s:%s" % (res["error_code"], res["reason"]))
else:
print("request api error")



def makeform(root,fields):
entries ={}
entries1 ={}
for field in fields:
row = Frame(root) #Frame就是屏幕上的一块矩形区域,多是用来作为容器(container)来布局窗体。
#文本或图像在背景内容区的位置:anchor
# 可选值为(n,s,w,e,ne,nw,sw,se,center)
# eswn是东南西北英文的首字母,表示:上北下南左西右东
lab = Label(row,width = 22,text = field + ":",anchor = 'w')
com = ttk.Combobox(row, state='readonly')
com['values'] = (currency)
com.current(0) #添加默认值为0
row.pack(side = TOP,fill = X,padx = 5,pady =5)
lab.pack(side = LEFT)
com.pack(side = RIGHT,expand = YES,fill =X)
entries[field] = com

for field1 in fields1:
row1 =Frame(root)
lab = Label(row1, width=22, text=field1 + ": ", anchor='w')
ent = Entry(row1)
ent.insert(0, "0")
row1.pack(side = TOP,fill = X,padx = 5,pady =5)
lab.pack(side=LEFT)
ent.pack(side=RIGHT, expand=YES, fill=X)
entries1[field1] = ent

return entries,entries1

if __name__ == '__main__':
root = Tk()
root.title('汇率转换器')
ents,ents1 = makeform(root,fields)
b1 = Button(root,text = 'Demand',
command = (lambda e =ents,e1=ents1:demand(e,e1)))
b1.pack(side = LEFT,padx = 5,pady =5)
b2 = Button(root, text='Exchange',
command=(lambda e=ents1: exchange(e)))
b2.pack(side=LEFT, padx=5, pady=5)
b3 = Button(root,text = 'Push into Datebases',
command = (lambda e =ents,e1=ents1:put_mysql(e,e1)))
b3.pack(side = LEFT,padx =5,pady =5)
b4 = Button(root,text = 'Quit',command = root.quit)
b4.pack(side = LEFT,padx = 5,pady = 5)
root.mainloop()