同时起两个线程,并保证顺序写入文件

144 阅读1分钟
class PingThread(threading.Thread):

    def __init__(self, start_time, end_time, delay, csv_file, ip_address):
        threading.Thread.__init__(self)
        self.task_start_time = common_util.str2date(start_time)
        self.task_end_time = common_util.str2date(end_time)
        self.delay = delay
        self.csv_file = csv_file
        self.ip_address = ip_address

    """
    执行执行start方法后,会调用该方法中的任务
    """

    def run(self) -> None:
        self.get_ping_time()

    """
    获取ping 的时间
    """

    def get_ping_time(self) -> None:
        # 如果当前时间没有到达开始时间,进行睡眠
        remaining_time_for_start = (self.task_start_time - datetime.now()).total_seconds()
        if remaining_time_for_start > 0:
            time.sleep(remaining_time_for_start)
        while True:
            # 记录开始时间
            start_time = time.time()
            self.ping_task()
            cost_time = time.time() - start_time
            sleep_time = self.delay - cost_time
            if sleep_time > 0:
                time.sleep(sleep_time)
            # else:
            #     print("访问ping花费时间过多:" + str(cost_time))

            # 线程结束
            if datetime.now() > self.task_end_time:
                break

    def ping_task(self):
        start_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        if platform.system().lower() == 'windows':
            avg_time = common_util.win_ping_avg_time(self.ip_address)
        else:
            avg_time = common_util.linux_ping_avg_time(self.ip_address)
        write_file(start_time + "," + avg_time + "\n", self.csv_file)


"""url调用响应时间的线程定义"""


class UrlThread(threading.Thread):
    def __init__(self, start_time, end_time, delay, csv_file, exit_id):
        threading.Thread.__init__(self)
        self.task_start_time = common_util.str2date(start_time)
        self.task_end_time = common_util.str2date(end_time)
        self.delay = delay
        self.csv_file = csv_file
        self.exit_id = exit_id

    def run(self):
        self.get_response_time()

    """
    根据url获取响应时间
    """

    def get_response_time(self):
        # 如果当前时间没有到达开始时间,进行睡眠
        remaining_time_for_start = (self.task_start_time - datetime.now()).total_seconds()
        if remaining_time_for_start > 0:
            time.sleep(remaining_time_for_start)
        while True:
            """
            下面逻辑保证同时触发启动
            """
            start_time = time.time()
            # 使用睡眠模拟调用url,获取响应时间
            self.url_task()
            cost_time = time.time() - start_time
            sleep_time = self.delay - cost_time
            if sleep_time > 0:
                time.sleep(sleep_time)
            # else:
            # print(self.exit_id+"访问url花费时间过多:" + str(cost_time))

            # 线程结束
            if datetime.now() > self.task_end_time:
                break

    def url_task(self):
        url = ""
        args = {"extId": self.exit_id}
        headers = {'Content-Type': 'application/json'}
        dt = datetime.now()
        start_time = dt.strftime('%Y-%m-%d %H:%M:%S')
        #如果链接出现异常,报-2,如果报-1,则是车端APP未开启
        url_delay_time = -2
        try:
            res = requests.post(url, headers=headers, data=json.dumps(args))
            response = res.json()
            url_delay_time = response['data']['delayTime']
            # print(f'"url_时间":{start_time} "url_响应时间":{url_delay_time}')
        except Exception as e:
            print(f"{self.exit_id}:response请求异常")
        write_file(str(start_time) + "," + str(url_delay_time) + ",", self.csv_file)
#写入文件的路径
root_path=common_util.files_name()
first_content = ""
second_content = ""
def write_file(content, csv_file):
    global first_content, second_content
    # 加锁保证顺序写入
    lock = threading.Lock()
    # lock.acquire 为true表示获取到锁,执行下面逻辑
    if lock.acquire():
        if content.endswith("\n"):
            second_content = content
        else:
            first_content = content
        # 获取锁
        if first_content != "" and second_content != "":
            try:
                with open(root_path + csv_file, "a+") as f:
                    f.write(first_content + second_content)
                    f.flush()
            finally:
                # 释放锁
                first_content = ""
                second_content = ""
                lock.release()


def start_record(start_time, end_time, exit_id, ip):
    vehicle_Name = common_util.vehicle_Name(exit_id)
    #此处文件名不能用:符号,最好不要包含空格,文件名包含空格,会自动在Linux系统中生成此文件,并加上''
    file_name = vehicle_Name + '~' + start_time.replace(":", "-") + '~' + end_time.replace(":", '-')
    # print(type(start_time))
    csv_file = file_name + ".csv"
    # 创建两个线程
    t1 = PingThread(start_time, end_time, 120, csv_file, ip)
    t2 = UrlThread(start_time, end_time, 120, csv_file, exit_id)
    # 写入表头
    with open(root_path + csv_file, "a+") as file:
        # 写入函数结果,需要将函数结果转为字符串
        file.write("url_start_time,url_time(ms),ping_start_time,ping_time(ms)\n")
    t1.start()
    t2.start()
    return csv_file