1

链接前文:Python实现命令行监控北京实时公交之一


开头先放上效果展示

在命令行输入 python bus.py -i,显示app基本信息,如下:

clipboard.png

在命令行输入 python bus.py 438,显示北京438路公交车的位置,如下:

clipboard.png

红色的B说明在梅园附近有一辆438公交车,并且会不断刷新。

GitHub地址 - https://github.com/Harpsichor...


命令行显示输出及美化

前文我们实现了获取公交车位置的函数,现在需要将其美化并输出到命令行中,这里分别使用docopt/prettytable/colorama三个库。

prettytable库和colorama

简单来说,prettytable可以将数据以表格的形式打印,colorama可以设置命令行中字体的颜色,直接上代码:

from prettytable import PrettyTable
from colorama import Fore, init

# colorama需要init使用
init()

# 函数接受4个参数
# data0/data1分别是往返站点信息的list,其中的元素也是list,结构是['id', 站名, 是否有公交车]
# time0/time1是往返线路运营时间
def print_direction_and_station(data0, data1, time0, time1):
    pt = PrettyTable()
    # 设置表头,为了美观往返之间留一个空列
    pt.field_names = ['#0', 'UP:' + time0, 'Bus0', '   ', '#1', 'DOWN:' + time1, 'Bus1']
    # 往返路线的站数可能不一致,取最大值作为行
    for i in range(max(len(data0), len(data1))):
        if i >= len(data0):
            r0 = [' '] * 3
        else:
            r0 = data0[i]
            # 'B'表示该车站附近有公交车
            if r0[2] == 'B':
                # 设置文本的颜色为红色
                r0[1] = Fore.RED + r0[1]
                # 去除红色,否则后面全是红的
                r0[2] = r0[2] + Fore.RESET
        if i >= len(data1):
            r1 = [' '] * 3
        else:
            r1 = data1[i]
            if r1[2] == 'B':
                r1[1] = Fore.RED + r1[1]
                r1[2] = r1[2] + Fore.RESET
        pt.add_row(r0 + ['   '] + r1)
    # 打印结果
    print(pt)

docopt

docopt可以读取一段字符串(通常是__doc__),并将其解析为命令行参数,例如在bus.py开头输入以下内容:

"""
Usage:
    bus <bus_code>
    bus [-ih]

Options:
    -h              Show help information
    -i              Show application information

Example:
    bus 438         Show stations, directions and positions of bus 438
"""

并使用from docopt import docopt引入模块,结尾代码如下:

if __name__ == "__main__":
    args = docopt(__doc__)
    print(args)

直接使用python bus.py运行,输出的结果是:

clipboard.png

从中不难发现,docopt解析了__doc__Usage的部分,将参数以字典的形式返回,我们改变输入命令的参数,返回的args字典对应的value也将不同。


前文中我们获取的公交车位置信息需要经过一些处理才能传给print_direction_and_station函数,结合命令行参数,代码如下:

if __name__ == "__main__":
    args = docopt(__doc__)
    b_code = args['<bus_code>']
    # 如果输入了<bus_code>参数
    if b_code:
        # 获取往返线路id
        [d0, _], [d1, _] = get_bus_direction(b_code)
        # 获取往返车站
        stations0 = get_bus_stations(b_code, d0)
        stations1 = get_bus_stations(b_code, d1)
        # 进入循环以刷新
        while 1:
            direction0 = []
            direction1 = []
            status0 = get_bus_status(b_code, d0, len(d0))
            status1 = get_bus_status(b_code, d1, len(d1))
            pos0 = status0['bus_position']
            # pos0_id/pos1_id 是有公交车的车站id
            pos0_id = [p['station_id'] for p in pos0]
            pos1 = status1['bus_position']
            pos1_id = [p['station_id'] for p in pos1]
            # 两个for循环构建传给print_direction_and_station参数
            for i, d in enumerate(stations0):
                bus = ' '
                if str(i+1) in pos0_id:
                    bus = 'B'
                direction0.append([i+1, d, bus])
            for i, d in enumerate(stations1):
                bus = ' '
                if str(i + 1) in pos1_id:
                    bus = 'B'
                direction1.append([i+1, d, bus])
            print_direction_and_station(direction0, direction1, status0['operation_time'], status1['operation_time'])
            # 每5s刷新一次
            sleep(5)

此时输入python bus.py 438,就可以显示上文图中的结果了,python bus.py -i也是同理,自定义一个print信息的函数即可。


Harpsichord1207
538 声望44 粉丝

前路漫漫