使用 lambda 冻结程序在 timeit 内调用 ftplib retrbinary()

Calling ftplib retrbinary() inside timeit using lambda freezes program

我正在尝试收集有关小型 LAN 中网络问题的一些指标,SSH 偶尔会断开连接并且 ping 显示出巨大的延迟(最多一分钟而不是不到一秒!)。

使用 timeit(我读到这是在调用某些代码片段时检查执行时间的好方法)我尝试从也在本地运行的 FTP 服务器下载一些数据, 测量时间并将其存储在日志文件中。

from ftplib import FTP
from timeit import timeit
from datetime import datetime

ftp = FTP(host='10.0.0.8')
ftp.login(user='****', passw='****')
ftp.cwd('updates/')
ftp.retrlines('LIST')

# Get timestamp when the download starts
curr_t = datetime.now()

print('Download large file and measure the time')
file_big_t = timeit(lambda f=ftp: f.retrbinary('RETR update_big', open('/tmp/update_big', 'wb').write))

print('Download medium file and measure the time')
file_medium_t = timeit(lambda f=ftp: f.retrbinary('RETR file_medium ', open('/tmp/file_medium ', 'wb').write))

print('Download small file and measure the time')
file_small_t = timeit(lambda f=ftp: f.retrbinary('RETR update_small', open('/tmp/update_small', 'wb').write))

# Write timestamp and measured timings to file
# ...

如果我在没有 timeit 的情况下调用 retrbinary(...),它可以正常工作。然而,上面的代码导致脚本在第一次 timeit 调用后立即冻结。

万一其他人想做我在问题中描述的事情,我找到了解决方案 here。出于某种原因,将 lambda 直接传递给 timeit 会导致我已经提到的行为。但是,如果 same lambda 首先传递给 timeit.Timer 的实例,并且调用该实例的 timeit() 函数,它就可以工作。

对于上面的例子(让我们只取file_big_t)我做了

file_big_timer = Timer(lambda f=ftp: f.retrbinary('RETR update_big', open('/tmp/update_big', 'wb').write))
file_big_t = file_big_timer.timeit()