[Python] 移动等待时间

[Python] 移动等待时间

考虑一种需求,client 向 server 发送一个请求,server 因为某种原因没有回复,或者回复失败。client 接受失败后等待一段时间;第二次再次请求,仍然失败,此时你想要根据连续失败次数延长等待时间;在每一次成功之后确定等待的时间不变(比如为 0)。

running_wait-time

有几种方案可以实现这种需要,根据 python 的闭包特性,编写一个 function 而非编写 class 就可以实现这个需求。1
完整代码在 github 上的链接

Server 端的代码通过 IPC 为 Client 提供服务,本 需求-solution 重在说明 Client 行为,Server 端代码是本主题不关心的。但是也放上来以供参考。

Client

详细实现细节/原理待有空 更新。

#!/usr/bin/env python3

"""
Author: Joseph Lin
E-mail: joseph.lin@aliyun.com
Social: https://github.com/RDpWTeHM
        https://me.csdn.net/qq_29757283
"""
import sys
# import os
from multiprocessing.connection import Client
# import time
from time import ctime
from time import sleep


def main():
    missions = [#"localhost", "google.com", "bing.com", "github.com",
                #"www.csdn.net",
                "yahoo.com", "google.com", "www.jd.com", "www.baidu.com",
                "www.amazon.com", "www.gitee.com",
    ]

    def timeoutsleep():
        _totimes = 0

        def runningsleep(IsTimeout):
            nonlocal _totimes  # fluent python - & 7.6 nonlocal
            if IsTimeout is False:
                _totimes = 0
            elif IsTimeout is True:
                _totimes += 1
                if __debug__: sleep(_totimes * 2)
                else:         sleep(_totimes * 5)
            else:
                raise Exception("<timeoutsleep> Error parameter gived!")
        return runningsleep

    tosleep = timeoutsleep()

    cconn = Client(("localhost", 15337), authkey=b"running_wait-time")

    try:
        for mission in missions:
            cconn.send("http://" + mission)
            page_source = cconn.recv()

            if "timeout" == page_source.lower():
                print("[{}] timeout in {}!".format(ctime(), mission))
                tosleep(True)
            else:
                print("[{}] get {} suucess!".format(ctime(), mission))
                tosleep(False)
    except EOFError:
        print("Server closed the IPC connection!", file=sys.stderr)
        raise SystemExit("Mission Interrupt due to server closed connection!")
    else:
        cconn.close()


if __name__ == "__main__":
    main()

Server

  • bug detect - 需要两次 Ctrl+C 才能完全退出程序。
    Server 端在 browser 运行 .get() 期间,接收到 SIGTERM/SIGINT 会被 selenium 库代码捕获,以至于不能正常执行我们编写的捕获 SIG* 运行代码。
    但是该 bug 目前对本 blog 要实现的功能无关,且不影响测试功能,暂时未解决。
#!/usr/bin/env python3

"""
Author: Joseph Lin
E-mail: joseph.lin@aliyun.com
Social: https://github.com/RDpWTeHM
        https://me.csdn.net/qq_29757283
"""
import os
import sys
# import time
from time import ctime
# from time import sleep
import signal

from multiprocessing.connection import Listener

from selenium import webdriver
from selenium.common.exceptions import TimeoutException

PATH = os.environ.get("PATH", None)
os.environ['PATH'] = "/usr/lib/chromium-browser:" + PATH


browser = webdriver.Chrome()
browser_bkup = browser  # just in case lost browser banding.

browser.implicitly_wait(20)
browser.set_script_timeout(20)    # lower timeout can be easy to
browser.set_page_load_timeout(20)


def handler_client(conn):
    while True:  # handle client until client close the connection
        try:
            recv = conn.recv()
        except EOFError:
            print("Connection closed at {}".format(ctime()))
            break
        except Exception as e:  # 如何在测试中跑到这个 condition???
            print("[Error] Unexcept Exception: ", e, file=sys.stderr)
            print("\tclose connection but not exit program!", file=sys.stderr)
            conn.close()
            break
        else:
            try:
                print("[{}][INFO] request {}".format(ctime(), recv))
                safe_get_tab = browser.window_handles[0]

                excute_script_str = "window.open('{}','handler_tab');".format("about:blank")
                browser.execute_script(excute_script_str)
                browser.switch_to.window('handler_tab')

                browser.get(recv)
            except TimeoutException as e:
                print("[{}][WARNING] get '{}' page source timeout!".format(ctime(), recv))
                print("\t", "=" * 15, "TimeoutException: ", "=" * 15, "\n", e)
                # browser.execute_script("window.stop();")
                page_source = "timeout"
            else:
                print("[{}][INFO] finish get '{}' page source".format(ctime(), recv))
                page_source = browser.page_source
            finally:
                browser.close()
                browser.switch_to.window(safe_get_tab)

                conn.send(page_source)


def server_handler(address, authkey):
    serv = Listener(address, authkey=authkey)
    while True:  # server act like daemon
        try:
            client_conn = serv.accept()

            handler_client(client_conn)
        except Exception:
            import traceback; traceback.print_exc()


def handler_everything():
    server_handler(("", 15337), authkey=b"running_wait-time")


def main():
    def sigterm_handler(signo, frame):
        # close the connection - use global queue!!!!
        browser_bkup.quit()
        raise SystemExit("\nreceive 'Ctrl+C'/'kill -15'/SIGTERM, program stop!")
    signal.signal(signal.SIGINT, sigterm_handler)
    signal.signal(signal.SIGTERM, sigterm_handler)

    try:
        handler_everything()
    except Exception as e:  # 报告一切错误
        print("[Error] Exception: ", e, file=sys.stderr)


if __name__ == "__main__":
    main()

Reference


  1. Fluent Python (流畅的 Python)&7.6 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值