Python运行时硬盘一直有写入如何排查和解决
现在在学习 Python,发现一件有件事不是太明白,我的 Python 程序在运行时一直有写硬盘的操作,又没有读取,我全部的操作在内存里完成,并没有涉及到文件读写,这个写硬盘来源在哪里?
Python 程序主要作用是截图并识别文字
用到三个:win32API、OpenCV 和 pytesseract
win32API 是用来截图,
OpenCV 是把截图转换成二值图
pytesseract 识别二值图,return 出识别结果。
在程序运行时,发现 win32 每次截图,win8.1 系统资源管理器都显示有 50kb/s 左右的写入操作,时间不到一秒。我对 win32API 截图操作以 200ms 间隔迭代了两万多次,发现硬盘一直在写入,速度大概在 53kb/s,但是在中间没有任何读取操作。
如果我的程序完整运行,在迭代过程中,发现资源管理器会显示硬盘写入速度在 170kb/s 左右。
不明白的,这个写入究竟写的是什么内容,我全部操作都在内存里完成,不涉及到写文件操作。
Python运行时硬盘一直有写入如何排查和解决
跟图片有关的缓存都是写在 temp 里的可以自己翻源码
这个问题我遇到过,排查硬盘写入可以从这几个方向入手:
1. 先定位是哪个进程在写
import subprocess
import sys
# Windows用Process Monitor,Linux/Mac用iotop
if sys.platform == "win32":
print("建议下载Process Monitor查看磁盘活动")
else:
try:
subprocess.run(["sudo", "iotop", "-o", "-P"], check=False)
except:
print("安装iotop: sudo apt install iotop")
2. 检查Python程序自身的文件操作 常见问题代码:
# 问题示例:频繁写入日志
import logging
logging.basicConfig(
level=logging.DEBUG,
filename='app.log', # 持续写入
filemode='a' # 追加模式
)
# 改为按大小或时间轮转
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler('app.log', maxBytes=1024*1024, backupCount=5)
3. 检查第三方库的缓存
# 很多库会缓存数据到磁盘
import tempfile
print(f"临时目录: {tempfile.gettempdir()}")
# 清理可能的大量缓存文件
import shutil, os
temp_dir = tempfile.gettempdir()
for item in os.listdir(temp_dir):
if item.startswith("python_"): # 示例匹配模式
path = os.path.join(temp_dir, item)
try:
if os.path.isfile(path):
os.unlink(path)
elif os.path.isdir(path):
shutil.rmtree(path)
except Exception as e:
print(f"无法删除 {path}: {e}")
4. 数据库操作检查
# SQLite自动提交可能导致频繁写入
import sqlite3
# 坏例子
conn = sqlite3.connect('test.db') # 默认autocommit=False但某些操作会触发
conn.execute("INSERT INTO table VALUES (?)", [data]) # 每次执行都可能写盘
# 改进:显式事务批量操作
conn = sqlite3.connect('test.db', isolation_level=None) # 或手动控制
cursor = conn.cursor()
cursor.execute("BEGIN")
for data in large_dataset:
cursor.execute("INSERT INTO table VALUES (?)", [data])
cursor.execute("COMMIT")
5. 使用监控工具定位
# 简单监控脚本
import psutil
import time
def monitor_io(pid=None, interval=2):
"""监控指定进程或所有Python进程的IO"""
if pid:
p = psutil.Process(pid)
print(f"监控进程 {pid} ({p.name()})")
else:
# 监控所有Python进程
python_procs = [proc for proc in psutil.process_iter()
if 'python' in proc.name().lower()]
while True:
if pid:
io = p.io_counters()
print(f"写字节数: {io.write_bytes / 1024:.1f}KB")
time.sleep(interval)
# 使用前安装: pip install psutil
快速排查步骤:
- 用系统工具(iotop/Process Monitor)找到具体进程
- 检查程序中的文件操作、日志配置
- 查看临时目录和缓存
- 数据库操作是否过于频繁
建议先确定是程序问题还是依赖库问题。
win32api 代码如下:
import win32gui
import win32ui
hwnd = win32gui.FindWindow(None, windowname)
wDC = win32gui.GetWindowDC(hwnd)
dcObj=win32ui.CreateDCFromHandle(wDC)
cDC=dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
#dataBitMap.SaveBitmapFile(cDC, bmpfilenamename)
我在这里就把 pycdc 转换成了 numpy,保存在变量里,在后面代码运行后,就 return 这个变量出去。
# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
非计算机专业,没有系统学过编程,对这些不是太明白。我用过 pillow 截图,这个要 50ms,速度不够快,win32API 只要 10ms,用 pillow 而这个也有写硬盘操作。像这种缓存,有没有办法避免它写,如果不想它写,该如何解决?
你去翻翻 pytesseract 的源码,有些使用他是调用 tesseract.exe 的,那样的话需要先把图片写入硬盘再让 exe 读取
谢了老哥

