栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

用PySimpleGui做户籍资料查询工具

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用PySimpleGui做户籍资料查询工具

用PySimpleGui做户籍资料查询工具 前言

最近手里有一张几千人的户籍信息表格,突发奇想,想用python做一个小工具,可以按照人名搜索,获取该人所在户的所有人信息,然后显示图片,个人详情页,方便查询
以前用tkinter做过一个从xls表格获取行信息填入doc,并批量打印的小工具,tkinter是比较好用,可是想做好看真心不容易,搜索之下发现了PySimpleGui,这个更加简单
学习python属于个人兴趣,没有接受系统学习,风格也是野路子,写下这篇心得纯粹是记录学习内容,毕竟功能实现都是自己一点点想的,没有参考别人的案例。同为初学者的可以看看,抛砖引玉。大神也请赐教。

逻辑部分 数据源

我手里有一份整村的村民户籍表,不是很完整,错误也比较多,没有身份证号,所以没有泄密嫌疑。表格是xls的,为了更好操作,先手动转成csv格式,当数据库用了。表格内容较多,我们主要用到的是姓名、性别、户主关系、电话号码,几项

需求分析

我想要实现的一个主要功能是,输入一个人名,在数据表中搜索到所有这个名字的人(当然有重名的),然后根据他的户主关系,找到他整户的人,并打印出来。这样有几个技术问题需要解决。。。(我本人纯属爱好,没有接触过算法,都是用最笨的方法解决)

思路及方法 获取csv所有行的内容

这是csv基础操作了,上代码

def open_csv():
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
    return reader
根据每行里“户主关系”内容,找到一共有多少户主,并将所有户主的序号记录

这个就是突发奇想了,我找到所有的户主,并把它们的序号单独存一个list,这样确定了被搜索的人的序号,就可以通过序号,确定他在哪两位“户主”之间,从而找到所有的家庭成员。ok,上代码

# 获取所有属性是户主的村民序号 存到huzhu_list列表并返回
def get_huzhu_list():
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['与户主关系'] == '户主':
                # print(row)
                huzhu_list.append(row['序号'])
        return huzhu_list
找到被搜索人在csv中的序号
# 根据姓名 获取她的序号
# 考虑到会有重名的情况,所以用一个列表name_id保存了所有了该名字的序号
def get_name_id(name):
    name_id = []
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['姓名'] == name:
                name_id.append(row['序号'])
                # print('序号是:' + name_id)
        return name_id
接下来,就是找到被搜索人全家了
# 这是核心了,通过用户序号 找到该户的户主和下一户的户主序号,从而计算出该户所有人的序号
def get_hole_family_id(huzhu_list, name_id):
    first = 0
    last = 0
    for i in huzhu_list:
        # 首先,huzhu_list里边是所有户主的id
        # 如果搜索的人就是户主,那么他的id就是该户的第一个人,
        # 先用huzhu_list.index(i)找到他在户主列表里的位置,+1 找到下一个户主的id
        # 然后在通过这个位置,找到下一个户主的id 说起来有点绕
        # 这里只是定位到下一个户主的位置,而不用-1 因为下边用到的
        # range(first,last)函数构建列表时正好是 first到last-1
        if int(i) == int(name_id):
            first = int(i)
            last = int(huzhu_list[huzhu_list.index(i) + 1])
            break
        # 如果要搜索的人不是户主,那么先找他的下一个户主的位置,再通过-1找到本户主的位置
        elif int(i) > int(name_id):
            last = int(huzhu_list[huzhu_list.index(i)])
            first = int(huzhu_list[huzhu_list.index(i) - 1])
            break
    family_id_list = [i for i in range(first, last)]
    return family_id_list

这样,我们得到了被搜索人全家的人员序号

再用两个方法,根据序号,获取csv文件里的整行信息
# 根据序号 定位到csv文件中的行
def get_content(name_id):
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['序号'] == name_id:
                print(row)
# 通过全家人的序号,获取全家人的信息,并全部添加到列表all_familly_list中
def get_hole_family_cont(family_id_list):
    all_familly_list = []
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            for id in family_id_list:
                if row['序号'] == str(id):
                    # row 是一个字典格式,需要用dict.values()将键值转化为列表
                    list3 = list(row.values())
                    # 从列表中找出我们需要的信息,从新创建一个列表,就得到了该人的信息
                    family_list = [list3[3], list3[4], list3[7], list3[6]]
                    all_familly_list.append(family_list)
        return all_familly_list

至此,通过一个人名,我们得到了他家所有人的信息,并全部装入一个列表里。下面就是做一个页面,把他们显示出来

界面部分 PySimpleGui介绍

网上介绍很多,我摘抄了一点过来,实现很简单,布局采用layout行式布局,很直观
1.import 库
2.layout UI布局
3.window 窗口显示
4.Event loop 事件循环,用户持续交互
5.close 关闭窗口

# 1 - The import
import PySimpleGUI as sg
# 2 - Layout definition
layout = [[sg.Text('My layout')],
    [sg.Input(key='-INPUT-')],
    [sg.Button('OK'), sg.Button('Cancel')] ]
# 3 - Create window
window = sg.Window('Design Pattern 3 - Persistent Window', layout)
# 4 - Event Loop
while True:
   event, values = window.read()
   if event in (None, 'Cancel'):
       break

# 5 - Close window
window.close()

效果是

基本很容易实现我想要的,其他不再累述,需要的可以去csdn找,很多很多

界面布局

通过修改一个案例,一番折腾,得到了我想要的布局如下


代码如下:

import PySimpleGUI as sg
from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu, 
    Canvas, Column, Col, Combo, frame, Graph, Image, InputText, Input, In, Listbox, LBox, Menu, Multiline, ML, MLine, 
    OptionMenu, Output, Pane, ProgressBar, Radio, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, 
    TreeData, VerticalSeparator, Window, Sizer


sg.theme('GreenTan')
list = [['    ','  ','户主','      ']]

col3 = Column([[frame('Information:', [[Text(), Column([[Text('户      数:  ')],
                                             [Text('人      数:  ')],
                                             [Text('低保人数:  ')],
                                             [Text('五保人数:  ')],],size=(210, 120), pad=(0, 0))]
                            ]
           )
     ]], pad=(0, 0))

col2 = Column([[frame('Accounts:', [[Column([
                    [Table(values=list,
                    headings=['  姓  名  ',' 性  别 ',' 属  性 ','   电     话   '],
                    max_col_width=300,
                    auto_size_columns=True,#自动调整列宽(根据上面第一次的values默认值为准,update时不会调整)
                    display_row_numbers=True,#序号
                    justification='center',#字符排列 left right center
                    num_rows=12,#行数
                    row_height=30,#行高
                    key='_table_',
                    font=('微软雅黑', 12),
                    text_color='black',
                    background_color='white',
                    enable_events=True,
                    bind_return_key=True,
                    tooltip='This is a table')]
                    , ], size=(450, 400),pad=(0, 0))]])]],pad=(0, 0))

col1 = Column([
    # Information frame
    [frame('Search:', [[Text(), Column([[Text('输入姓名:')],
                        [Input(key='-USERID-IN-', size=(16, 1)),
                          Button('Search', key='-SEAR-')],
                         ], size=(195, 120), pad=(0, 0))]])], ], pad=(0, 0))


layout = [[col1,col3], [col2]]

window = Window('人员信息查询', layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEAR-':
        #print(values['-LIST-'][0])
        sg.popup('This is {}'.format(values['_table_'][0]))

window.close()

现在逻辑部分和界面都有了,把他们融合

这一点颇费脑筋,无奈基础太差,暂时不用面向对象了
基本方法是通过按钮事件的触发,调用逻辑代码,实现功能,并通过更新窗口,使结果显示出来

小技巧

不算技巧吧,是PySimpleGui一个比较方便的地方,每个窗口组件都有一个key属性和一个value属性(text没有),key是组件的名字,value是他要显示的内容,通过window[‘key’],可以定位该组件,通过window[‘key’].update(‘value’),可以直接将value更新到组件的value属性

最终界面

完整代码
import csv
import PySimpleGUI as sg
from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu, 
    Canvas, Column, Col, Combo, frame, Graph, Image, InputText, Input, In, Listbox, LBox, Menu, Multiline, ML, MLine, 
    OptionMenu, Output, Pane, ProgressBar, Radio, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, 
    TreeData, VerticalSeparator, Window, Sizer

num = 0
# 搜索所有的户主 并将他们的序号填入列表 用来调取整户信息
huzhu_list = []


# 通过DictReader方法打开csv文件,可以做到搜索功能
def open_csv():
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
    return reader


# 获得总户数
def get_familly_num():
    familly_num = 0
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['与户主关系'] == '户主':
                familly_num += 1
                # print(row)
        return familly_num


# 获得总人数
def get_people_num():
    people_num = 0
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            people_num += 1
            # print(row)
        return people_num


# 获取所有属性是户主的村民序号 存到huzhu_list列表并返回
def get_huzhu_list():
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['与户主关系'] == '户主':
                # print(row)
                huzhu_list.append(row['序号'])
        return huzhu_list


# 根据姓名 获取她的序号
# 考虑到会有重名的情况,所以用一个列表name_id保存了所有了该名字的序号
def get_name_id(name):
    name_id = []
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['姓名'] == name:
                name_id.append(row['序号'])
                # print('序号是:' + name_id)
        return name_id


# 根据序号 定位到csv文件中的行
def get_content(name_id):
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if row['序号'] == name_id:
                print(row)


# 这是核心了,通过用户序号 找到该户的户主和下一户的户主序号,从而计算出该户所有人的序号
def get_hole_family_id(huzhu_list, name_id):
    first = 0
    last = 0
    for i in huzhu_list:
        # 首先,huzhu_list里边是所有户主的id
        # 如果搜索的人就是户主,那么他的id就是该户的第一个人,
        # 先用huzhu_list.index(i)找到他在户主列表里的位置,+1 找到下一个户主的id
        # 然后在通过这个位置,找到下一个户主的id 说起来有点绕
        # 这里只是定位到下一个户主的位置,而不用-1 因为下边用到的
        # range(first,last)函数构建列表时正好是 first到last-1
        if int(i) == int(name_id):
            first = int(i)
            last = int(huzhu_list[huzhu_list.index(i) + 1])
            break
        # 如果要搜索的人不是户主,那么先找他的下一个户主的位置,再通过-1找到本户主的位置
        elif int(i) > int(name_id):
            last = int(huzhu_list[huzhu_list.index(i)])
            first = int(huzhu_list[huzhu_list.index(i) - 1])
            break
    family_id_list = [i for i in range(first, last)]
    return family_id_list

# 通过全家人的序号,获取全家人的信息,并全部添加到列表all_familly_list中
def get_hole_family_cont(family_id_list):
    all_familly_list = []
    with open('sunzhuang.csv', 'r') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            for id in family_id_list:
                if row['序号'] == str(id):
                    # row 是一个字典格式,需要用dict.values()将键值转化为列表
                    list3 = list(row.values())
                    # 从列表中找出我们需要的信息,从新创建一个列表,就得到了该人的信息
                    family_list = [list3[3], list3[4], list3[7], list3[6]]
                    all_familly_list.append(family_list)
        return all_familly_list

    # print(first)

    # print(huzhu_list)


sg.theme('GreenTan')

col3 = Column([[frame('Information:', [[Text(), Column([[Text('户      数:  '), Input(key='-hushu-', size=(10, 1))],
                                                        [Text('人      数:  '), Input(key='-renshu-', size=(10, 1))],
                                                        [Text('低保人数:  '), Input(key='-dibao-', size=(10, 1))],
                                                        [Text('五保人数:  '), Input(key='-wubao-', size=(10, 1))], ],
                                                       size=(210, 120), pad=(0, 0))]
                                       ]
                      )
                ]], pad=(0, 0))

col2 = Column([[frame('Accounts:', [[Column([
    [Table(values=[['', '', '', '']],
           headings=['  姓  名  ', ' 性  别 ', ' 属  性 ', '     身 份 证 号     '],
           max_col_width=300,
           auto_size_columns=True,  # 自动调整列宽(根据上面第一次的values默认值为准,update时不会调整)
           display_row_numbers=True,  # 序号
           justification='center',  # 字符排列 left right center
           num_rows=12,  # 行数
           row_height=30,  # 行高
           key='_table_',
           font=('微软雅黑', 12),
           text_color='black',
           background_color='white',
           enable_events=True,
           bind_return_key=True,
           tooltip='This is a table')]
    , ], size=(450, 400), pad=(0, 0))]])]], pad=(0, 0))

col1 = Column([
    # Information frame
    [frame('Search:', [[Text(), Column([[Text('输入姓名:')],
                                        [Input(key='-USERID-IN-', size=(15, 1)),
                                         Button('Search', key='-SEAR-')],
                                        ], size=(195, 120), pad=(0, 0))]])], ], pad=(0, 0))

layout = [[col1, col3], [col2]]

window = Window('人员信息查询', layout)

while True:
    event, values = window.read()
    print(event, values)

    familly_num = get_familly_num()
    people_num = get_people_num()

    window['-hushu-'].update(familly_num)
    window['-renshu-'].update(people_num)

    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEAR-':
        # print(values['-LIST-']])
        if values['-USERID-IN-'] != '':

            name = values['-USERID-IN-']
        else:
            sg.popup('输入一个人名,比如:张三')
            name = '张三'
        id_list = get_name_id(name)
        list1 = get_huzhu_list()
        all_list = []
        num = 0
        for id in id_list:
            family_id_list = get_hole_family_id(list1, id)
            familly_list = get_hole_family_cont(family_id_list)
            num += 1
            for i in familly_list:
                all_list.append(i)
        window['_table_'].Update(all_list)

        sg.popup('一共找到{}户'.format(num))

window.close()
总结

写这个小东西,从构思,查资料,写代码,查bug,用了一整天的时间,对我一个小白爱好者来说还是挺有成就感的。后续将会继续添加照片显示,家庭成员详细信息页面,和添加、删除、修改功能,实现了再分享。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/294532.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号