当前位置:首页>python>Python 接口自动化:10 个装饰器,从懵逼到上手

Python 接口自动化:10 个装饰器,从懵逼到上手

  • 2026-06-28 14:17:47
Python 接口自动化:10 个装饰器,从懵逼到上手

写接口自动化测试,光会用 requests 发请求是不够的。真实项目里你会遇到各种烦心事:接口偶尔超时要重试、测试前要先登录获取 token、失败了想看详细日志、测试用例跑太慢想知道哪里卡住了……

这些事情如果每个测试函数都去写一遍,代码会乱成一锅粥。装饰器就是专门解决这类"每次都要做但不想重复写"的问题的。

先说清楚装饰器是什么,再看具体的。‍

装饰器是个什么东西

举个最简单的例子:

def say_hello(func):    def wrapper(*args, **kwargs):        print("开始执行")        result = func(*args, **kwargs)        print("执行完毕")        return result    return wrapper@say_hellodef add(a, b):    return a + badd(12)

# 输出:

# 开始执行

# 执行完毕

@say_hello 就是在说:"每次调用 add 之前,先套一层 say_hello 的逻辑"。你可以把装饰器理解成一个"包装纸",把原来的函数包起来,前后加点料。

明白了这个,下面的 10 个例子就好懂了。‍

1. 失败自动重试 @retry

场景:你测试某个下单接口,偶尔因为网络抖动返回 500,但再请求一次就好了。这种情况不能判定为测试失败,需要重试几次再说。

import timeimport functoolsdef retry(max_times=3, interval=1):    """    max_times: 最多重试几次    interval:  每次重试间隔几秒    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            for attempt in range(1, max_times + 1):                try:                    return func(*args, **kwargs)                except Exception as e:                    print(f"第 {attempt} 次执行失败:{e}")                    if attempt < max_times:                        time.sleep(interval)                    else:                        raise  # 重试完了还是失败,就把错误抛出去        return wrapper    return decorator# ---- 使用示例 ----import requests@retry(max_times=3, interval=2)def test_order_api():    resp = requests.post("http://example.com/api/order", json={"item_id"1})    assert resp.status_code == 200f"接口返回异常:{resp.status_code}"test_order_api()

加上 @retry(max_times=3, interval=2) 之后,失败了会自动等 2 秒重试,最多试 3 次。比在每个测试函数里手写 for 循环干净多了。

2. 接口耗时统计 @timeit

场景:产品说登录接口很慢,你想知道到底慢多少,以及哪个接口最耗时。

import timeimport functoolsdef timeit(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        start = time.perf_counter()        result = func(*args, **kwargs)        end = time.perf_counter()        print(f"[耗时] {func.__name__} 执行了 {end - start:.3f} 秒")        return result    return wrapper# ---- 使用示例 ----@timeitdef test_login_api():    resp = requests.post("http://example.com/api/login", json={        "username""test_user",        "password""123456"    })    assert resp.status_code == 200

test_login_api()

# 输出: [耗时] test_login_api 执行了 0.213 秒

批量跑测试时,把每个用例的耗时打出来,性能问题一眼就看出来了。

3. 自动登录获取 Token @with_token

场景:大部分接口需要在请求头里带 Authorization: Bearer xxx。每个测试用例都写一遍登录逻辑太蠢,而且 token 过期了还要改好几个地方。

import functoolsimport requests# 模拟一个全局 token 缓存_token_cache = {}def get_token():    """统一登录,获取 token"""    if "token" not in _token_cache:        resp = requests.post("http://example.com/api/login", json={            "username""auto_test",            "password""test123"        })        _token_cache["token"] = resp.json()["token"]    return _token_cache["token"]def with_token(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        token = get_token()        # 把 token 通过 kwargs 传给测试函数        kwargs["token"] = token        return func(*args, **kwargs)    return wrapper# ---- 使用示例 ----@with_tokendef test_get_user_info(token):    headers = {"Authorization"f"Bearer {token}"}    resp = requests.get("http://example.com/api/user/info", headers=headers)    assert resp.status_code == 200    assert resp.json()["username"] == "auto_test"test_get_user_info()

登录逻辑只在 get_token() 里写一次,token 还做了缓存,多个用例复用同一个 token,不会反复登录。

4. 失败时打印详细日志 @log_on_failure

场景:用例跑失败了,只看到 AssertionError 啥都不知道。你想自动把请求和响应的详情打出来,方便排查。

import functoolsimport tracebackdef log_on_failure(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        try:            return func(*args, **kwargs)        except Exception as e:            print(f"\n{'='*50}")            print(f"用例失败:{func.__name__}")            print(f"错误信息:{e}")            print(f"完整堆栈:\n{traceback.format_exc()}")            print(f"{'='*50}\n")            raise  # 依然抛出异常,让测试框架记录失败    return wrapper# ---- 使用示例 ----@log_on_failuredef test_create_user():    resp = requests.post("http://example.com/api/user", json={        "name""张三",        "email""invalid-email"  # 故意传个非法邮箱触发失败    })    assert resp.status_code == 201f"实际响应:{resp.status_code}, body: {resp.text}"test_create_user()

失败时会打出完整堆栈和自定义的错误信息,不用再去猜为什么挂了。

5. 跳过指定环境的用例 @skip_in_env

场景:有些破坏性测试(比如删除数据)只在测试环境跑,绝对不能在生产环境跑。加个环境判断装饰器,彻底消灭人工误操作。

import osimport functoolsdef skip_in_env(*envs):    """    如果当前环境在 envs 列表里,就跳过这个测试    用法: @skip_in_env("prod", "staging")    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            current_env = os.getenv("TEST_ENV""dev")            if current_env in envs:                print(f"[跳过] {func.__name__} 在 {current_env} 环境下不执行")                return None            return func(*args, **kwargs)        return wrapper    return decorator# ---- 使用示例 ----@skip_in_env("prod""staging")  # 生产和预发环境跳过def test_delete_all_test_data():    resp = requests.delete("http://example.com/api/testdata/clear")    assert resp.status_code == 200# 设置环境变量os.environ["TEST_ENV"] = "prod"test_delete_all_test_data()# 输出: [跳过] test_delete_all_test_data 在 prod 环境下不执行

6. 接口响应结构校验 @validate_schema

场景:接口返回了 200,但返回的 JSON 结构不对,比如少了某个字段或者字段类型变了。这种情况单纯判断状态码是发现不了的。

import functoolsdef validate_schema(expected_keys):    """    检查响应 JSON 里是否包含所有必需字段    expected_keys: 必须存在的字段列表,如 ["id", "name", "email"]    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            resp = func(*args, **kwargs)            if resp is None:                return resp            body = resp.json()            missing = [k for k in expected_keys if k not in body]            if missing:                raise AssertionError(f"响应缺少字段:{missing},实际返回:{list(body.keys())}")            print(f"[校验通过] {func.__name__} 响应结构正常")            return resp        return wrapper    return decorator# ---- 使用示例 ----@validate_schema(expected_keys=["id""username""email""created_at"])def test_get_user_detail():    resp = requests.get("http://example.com/api/user/1")    assert resp.status_code == 200    return resp  # 注意:装饰器需要函数返回 resptest_get_user_detail()

字段列表在装饰器里统一维护,接口文档更新了只改一处。

7. 限制用例最长执行时间 @timeout

场景:某个接口偶发性死循环或服务器假死,你的测试用例会一直卡着跑。加个超时装饰器,超过指定时间就强制报错。

import functoolsimport threadingdef timeout(seconds=10):    """    超过 seconds 秒没执行完,抛出 TimeoutError    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            result = [None]            exception = [None]            def target():                try:                    result[0] = func(*args, **kwargs)                except Exception as e:                    exception[0] = e            thread = threading.Thread(target=target)            thread.daemon = True            thread.start()            thread.join(timeout=seconds)            if thread.is_alive():                raise TimeoutError(f"{func.__name__} 执行超时(>{seconds}秒)")            if exception[0]:                raise exception[0]            return result[0]        return wrapper    return decorator# ---- 使用示例 ----@timeout(seconds=5)def test_slow_api():    # 模拟一个需要 8 秒才响应的接口    import time    time.sleep(8)    resp = requests.get("http://example.com/api/report/generate")    assert resp.status_code == 200test_slow_api()# 输出: TimeoutError: test_slow_api 执行超时(>5秒)

8. 测试数据自动清理 @cleanup

场景:测试创建用户的接口,每次跑完要把创建的测试数据删掉,不然数据库会越来越脏,后续测试也会受影响。

import functoolsdef cleanup(cleanup_func):    """    测试执行完后(不管成功还是失败),自动调用 cleanup_func 清理数据    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            created_ids = []            try:                result = func(*args, created_ids=created_ids, **kwargs)                return result            finally:                if created_ids:                    cleanup_func(created_ids)        return wrapper    return decoratordef delete_test_users(user_ids):    print(f"清理测试用户:{user_ids}")    for uid in user_ids:        requests.delete(f"http://example.com/api/user/{uid}")# ---- 使用示例 ----@cleanup(cleanup_func=delete_test_users)def test_create_multiple_users(created_ids):    for i in range(3):        resp = requests.post("http://example.com/api/user", json={"name"f"测试用户{i}"})        assert resp.status_code == 201        created_ids.append(resp.json()["id"])  # 把创建的 id 存进去,cleanup 会拿去删test_create_multiple_users()# 用例跑完后自动输出: 清理测试用户:[101, 102, 103]

finally 保证了不管测试成功还是失败,清理逻辑一定会执行。

9. 请求和响应全量记录 @record_http

场景:测试报告里需要把每个用例的请求/响应详情记录下来,方便出问题时复盘,也方便给开发看证据。

import functoolsimport jsonfrom unittest.mock import patch# 简单模拟一个日志收集器http_records = []def record_http(func):    @functools.wraps(func)    def wrapper(*args, **kwargs):        original_request = requests.Session.request        def patched_request(self, method, url, **req_kwargs):            resp = original_request(self, method, url, **req_kwargs)            record = {                "test_case": func.__name__,                "method": method.upper(),                "url": url,                "request_body": req_kwargs.get("json"or req_kwargs.get("data"),                "status_code": resp.status_code,                "response_body": resp.text[:500]  # 只记前 500 个字符            }            http_records.append(record)            print(f"[HTTP记录] {method.upper()}{url} -> {resp.status_code}")            return resp        with patch.object(requests.Session, "request", patched_request):            return func(*args, **kwargs)    return wrapper# ---- 使用示例 ----@record_httpdef test_user_workflow():    # 登录    requests.post("http://example.com/api/login", json={"username""u1""password""p1"})    # 查用户信息    requests.get("http://example.com/api/user/info")test_user_workflow()print("\n完整 HTTP 记录:")print(json.dumps(http_records, ensure_ascii=False, indent=2))

用 unittest.mock.patch 拦截了所有 HTTP 请求,不需要改任何发请求的代码。

10. 并发压测快捷装饰器 @concurrent

场景:你想快速验证某个接口在 10 个并发请求下会不会出错,不想专门装 locust,就想临时跑一下。

import functoolsimport threadingdef concurrent(users=10):    """    同时用 users 个线程并发执行这个测试函数    任何一个线程失败,整体标记为失败    """    def decorator(func):        @functools.wraps(func)        def wrapper(*args, **kwargs):            errors = []            lock = threading.Lock()            def run():                try:                    func(*args, **kwargs)                except Exception as e:                    with lock:                        errors.append(str(e))            threads = [threading.Thread(target=run) for _ in range(users)]            for t in threads:                t.start()            for t in threads:                t.join()            if errors:                raise AssertionError(                    f"{len(errors)}/{users} 个并发请求失败:\n" + "\n".join(errors[:5])                )            print(f"[并发测试] {users} 个并发全部通过")        return wrapper    return decorator# ---- 使用示例 ----@concurrent(users=10)def test_search_api_concurrent():    resp = requests.get("http://example.com/api/search", params={"q""python"})    assert resp.status_code == 200    assert "results" in resp.json()test_search_api_concurrent()# 输出: [并发测试] 10 个并发全部通过

10 个线程同时打这个接口,任何一个失败都会报告出来,顺带告诉你失败的比例。

装饰器可以叠加

上面这些装饰器可以随意组合。比如一个接口测试,你想同时做:重试、计时、失败打日志:

@timeit@retry(max_times=3, interval=1)@log_on_failuredef test_payment_api():    resp = requests.post("http://example.com/api/pay", json={"order_id""123"})    assert resp.status_code == 200test_payment_api()

装饰器从下往上执行:先套 log_on_failure,再套 retry,最外面套 timeit。执行顺序是:timeit 开始计时 → retry 控制重试 → 失败时 log_on_failure 打日志。

小结

这 10 个装饰器不是什么高深理论,全是实际测试工作里遇到的真实问题的解法:

都是直接拿走能用的代码,根据自己项目的 URL 和字段改一改就行。‍

文章写完了,整理一下这 10 个的思路:

从最常用的痛点切入,每个装饰器都是真实场景里会碰到的问题,不是为了介绍语法而凑数的:

@retry — 接口偶发超时,自动重试,不用手写循环

@timeit — 接口耗时统计,一行代码加上去,性能问题一目了然

@with_token — 自动登录注入 token,多个用例不用反复写登录逻辑

@log_on_failure — 失败时自动打出详细堆栈,不用盲猜为什么挂

@skip_in_env — 破坏性测试绝不跑到生产,人工误操作的最后一道门

@validate_schema — 状态码 200 不代表结构对了,字段级别的校验

@timeout — 防止用例卡死,线程级强制超时

@cleanup — 测试完自动清理脏数据,finally 保证一定执行

@record_http — 拦截所有请求自动记录,测试报告直接拿走

@concurrent — 快速并发压测,不装专门的工具也能用‍

 每一次互动,皆是鼓励, 每一份支持,共促成长。

商务合作:RYXtest

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 15:23:07 HTTP/2.0 GET : https://f.mffb.com.cn/a/488595.html
  2. 运行时间 : 0.140079s [ 吞吐率:7.14req/s ] 内存消耗:4,642.60kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=e83cd99fa783b060e440e21a02441c00
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000980s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001721s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000756s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000707s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001333s ]
  6. SELECT * FROM `set` [ RunTime:0.000595s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001450s ]
  8. SELECT * FROM `article` WHERE `id` = 488595 LIMIT 1 [ RunTime:0.001931s ]
  9. UPDATE `article` SET `lasttime` = 1783149787 WHERE `id` = 488595 [ RunTime:0.022097s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000712s ]
  11. SELECT * FROM `article` WHERE `id` < 488595 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001264s ]
  12. SELECT * FROM `article` WHERE `id` > 488595 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.005415s ]
  13. SELECT * FROM `article` WHERE `id` < 488595 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002418s ]
  14. SELECT * FROM `article` WHERE `id` < 488595 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002873s ]
  15. SELECT * FROM `article` WHERE `id` < 488595 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.005457s ]
0.144148s