夜思

欢迎有共同爱好的人一起谈论技术

Python实现多进程ping并记录到excel

__author__ = 'Jimmy'
"""
说明:该程序通过访问数据库读取数据,然后写进excel表格,在对表格里的ip进行ping测试,
如果不通则记录时间,下次测试记录上次不通的时间差,这样就可以实现掉线时长!
"""
import threading,subprocess,psycopg2,datetime,os,openpyxl,time
import win32con, win32api
import socket
from tqdm import tqdm
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
try:
    # Python3
    from queue import Queue
except ImportError:
    # Python2
    from Queue import Queue
def getData():  # 连接postgres数据库,并执行sql语句,获取结果
    conn=psycopg2.connect(database="###",user="###",password="#########",host="############",port="5432")
    print("Opened database successfully")
    cur=conn.cursor()
    sql = "SELECT  distinct(network_addr), name, camera_pol_number,longitude,latitude from v_tz where name LIKE 'T%'"
    cur.execute(sql)
    columnRows = cur.fetchall()
    conn.commit()
    cur.close()
    conn.close()
    return columnRows
def check_alive(i, queue):  # 检测IP是否通
    while True:
        k, ip = queue.get()
        if ip is None:
            break
        result = subprocess.call('ping -w 1000 -n 1 %s' %ip, stdout=subprocess.PIPE, shell=True)  # 调用windows的cmd命令pingIP返回
        if result == 0:
            ws.cell(k, 7, "online")
            """
            h = subprocess.getoutput('ping -n 1 ' + ip)
            returnnum = h.split('平均 = ')[1]
            ws.cell(k, 6, returnnum)  #  测试点位延时
            #info = ('\033[32m%s\033[0m 能ping通,延迟平均值为:%s' %(ip,returnnum))
            """
        else:
            global offs
            offs += 1
            c = 1
            with open('OffLine.txt','a') as f:  # 不在线的写入文件
                f.write(str(nowTime) + " " + ip + '\n')
            ws.cell(k, c+6, "offline")
            if ws.cell(k, col-1).value == None:   # 如果表格里没有记录时间,则按照最新时间记录进去
                DXtime = nowTime
            else:
                DXtime = datetime.datetime.strptime(str(ws.cell(k, col-1).value), '%Y-%m-%d %H:%M:%S')  # 如果表格里面有时间则将现在时间减去表格时间求时间差
            t1 = (nowTime-DXtime).days*24+(nowTime-DXtime).seconds/3600  # 相差时间按小时计算
            if ws.cell(k, col).value == None:  # 如果表格第7列中没有数据,则直接填入上面计算的时间差
                ws.cell(k, c+8, str('%.2f' %t1))
            else:  # 如果表格第7列中有数据,则将该数据加上上面计算的时间差,统计出点位掉线总时间
                t2 = float(ws.cell(k, col).value)+t1
                ws.cell(k, c+8, str('%.2f' %t2))
            ws.cell(k, c+7, str(nowTime))  #  在第6列填上最新监测时间
        queue.task_done()
def writeDataToExcel():
    ws.cell(1, 1, "IP地址")
    ws.cell(1, 2, "点位名称")  # 在第一行第二列填入字符
    ws.cell(1, 3, "点位编号")
    ws.cell(1, 4, "经度")
    ws.cell(1, 5, "纬度")
    ws.cell(1, 6, "延时")
    ws.cell(1, 7, "在线状态")
    ws.cell(1, 8, "检测时间")
    ws.cell(1, 9, "掉线时长")
    for i in range(0, rows2):  # 将数据库中获取的数据填入excel中(从第二行开始)
        ws.append([str(columnRows[i][0]),str(columnRows[i][1]),str(columnRows[i][2]),str(columnRows[i][3]),str(columnRows[i][4])])
def senmail(text_msg):
    mail_host = "########"  #设置服务器
    mail_user = "##########"    #用户名
    mail_pass = "********"   #口令
    sender = '##########@#####.com'
    receivers = ['###########@######.com']   # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
    message = MIMEMultipart()
    test_message = MIMEText(text_msg, 'plain', 'utf-8')
    message.attach(test_message)
    def add_excel(xlsx_file,xlsx_name):
        msg_xlsx = MIMEText(open(xlsx_file,'rb').read(),'base64','utf-8')
        msg_xlsx.add_header('Content-Disposition', 'attachment', filename=xlsx_name)
        return msg_xlsx
    message_xlsx = add_excel('ip_tables.xlsx','ip_tables.xlsx')
    message.attach(message_xlsx)
    message['From'] = "chaozhou"
    message['To'] =  "chaozhou3"
    subject = '开始测试项目点位'
    message['Subject'] = subject
    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)    # 25 为 SMTP 端口号
        smtpObj.login(mail_user,mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print ("执行成功")
    except smtplib.SMTPException:
        print ("Error: 执行失败")
if __name__ == '__main__':
    time_start=time.time()
    print("导出增补点位数据及测试点位在线情况!(make sure the DBserver is online)")
    print("Author@Jimmy!,email:song179101723@163.com")
    nowTime=datetime.datetime.strptime(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), '%Y-%m-%d %H:%M:%S')
    hostname = socket.gethostname()
    myaddr = socket.gethostbyname(hostname)
    col = 9
    columnRows = getData()
    rows2 = len(columnRows)  # 获取数据库的数据数量
    cells = []
    offs = 0
    ip_queue = Queue()
    mon = str(datetime.datetime.now().month) + "月"
    if os.path.exists("ip_tables.xlsx"):  # 判断excel文件是否存在,如果存在直接打开
        print("ip_tables.xlsx is Exist")
        win32api.SetFileAttributes('ip_tables.xlsx', win32con.FILE_ATTRIBUTE_ARCHIVE)  # 保存excel文件前将该文件属性设置成可写
        wb = openpyxl.load_workbook("ip_tables.xlsx")
        # print(wb.sheetnames)
        if mon in wb.sheetnames:
            ws = wb[mon]
        else:
            ws = wb.create_sheet(mon)
            writeDataToExcel()
        columns = ws.max_column  # 获取表格1的最大列数
        rows = ws.max_row  # 获取表格1的最大行数
        for i in range(2,rows+1):
            v = ws.cell(row=i, column=1).value
            #print(v)
            ip_queue.put([i, v])  # 已数以组方式加入队列
        """
        for cell in list(ws.columns)[0]:  # 获取表格第一列的数据保存在cells数组中
            cells.append(cell.value)
        for ip2 in columnRows:
            if ip2[0] not in cells:  # 判断数据库中提取的IP是否在excel中存在,如果不存在则在表格后面加上,如果存在则pass
                rows += 1
                ws.cell(rows, 1, str(ip2[0]))
                ws.cell(rows, 2, str(ip2[1]))
                ws.cell(rows, 3, str(ip2[2]))
                ws.cell(rows, 4, str(ip2[3]))
                ws.cell(rows, 5, str(ip2[4]))
            else:
                pass
        """

    else:  # 如果excel文件不存在,则新建文件
        print("Create NEW File ip_tables.xlsx!")
        wb = openpyxl.Workbook()  # 新建一个工作表
        ws = wb.create_sheet(mon)
        writeDataToExcel()
    threads = []
    for i in tqdm(range(20)):  #  tqdm生成程序执行进度tqdm
        thread = threading.Thread(target=check_alive, args=(i, ip_queue))
        thread.setDaemon(True)  # 指定所构建的线程是否为后台线程
        thread.start()
    ip_queue.join()
    #  win32api.SetFileAttributes('ip_tables.xlsx', win32con.FILE_ATTRIBUTE_ARCHIVE)  # 保存excel文件前将该文件属性设置成可写
    wb.save('ip_tables.xlsx')
    wb.close()
    win32api.SetFileAttributes('ip_tables.xlsx', win32con.FILE_ATTRIBUTE_READONLY)  # 保存excel文件后将该文件属性设置成只读,避免被改动
    #print("Finished,共计点位数量为:%s,共掉线数量为:%s" % (rows2, offs))
    with open('OffLine.txt','a') as f:  # 不在线的写入文件
            f.write("共计点位数量为:"+str(rows)+",共掉线数量为:"+str(offs)+ '\n')
    mesg = str("本机%s IP为%s!本次统计点位数量为:%s个,掉线数量为:%s个" % (hostname, myaddr, rows2, offs))
    senmail(mesg)  # 打包附件发送邮件
    time_end=time.time()
    print('totally cost',time_end-time_start)

本代码中有个进度条的一直没办法调整好,因为设计到多线程,没办法按照循环进度来处理,如果需要做则记录每个进程处理时间来做。暂未实现


评论