如何在 python/windows 下对 I/O 事务设置超时并取消它?



我偶尔会有问题的SD卡,其中单个文件不可复制,但也没有出现错误,只有在有时出错之后。我用于复制的工具在等待期间也不会重新起作用。他们不能被杀死。只有卸下 SD 卡读卡器才有帮助。我目前正在使用Windows。 因此,我正在尝试编写一个工具,该工具通过取消阻塞I/O操作在超时后跳过文件复制操作。

我当然尝试编写一些代码,在一段时间后杀死进程,但如前所述,即使使用管理员权限,这也不起作用。所以我尝试使用Windows的低级操作来提交,如果需要,还可以取消I/O操作,我发现pywin32在python下很方便(但很少记录(。不幸的是,它没有按预期工作。win32 方法都无法按预期工作(例如忽略超时、非工作事务标识符(,Python 多处理功能都没有用。相反,它们会导致障碍(线程之间无法直接传递句柄(。这是我到目前为止的代码(从不同来源复制在一起(:

import multiprocessing
import time
import win32file,win32transaction
def win32copy(src,dst,transactions):
transaction=win32transaction.CreateTransaction(Timeout=5000) #the timeout could have been a solution, but has absolutely no effect
transactions.append(str(win32transaction.GetTransactionId(transaction))) #the transaction itself is not pickable
win32file.CopyFileEx(src, dst, Transaction=transaction) #the I/O block already happens here, surprisingly, and not later at the commit
win32transaction.CommitTransactionAsync(transaction) #that is never reached. Hence, doesn't matter if CommitTransaction() or CommitTransactionAsync()is used 
print "transaction submitted"

if __name__ == '__main__':
manager = multiprocessing.Manager()
transactions = manager.list() # for sharing objects between threads
src='D:\sdcard\somefile'
dst='C:\harddisk\somefile'
p = multiprocessing.Process(target=win32copy, args=(src,dst,transactions))
p.start()
time.sleep(10) #sleep for 10sec
print "waiting finished"
while p.is_alive():
print "running... let's kill it...",transactions[0] #here is the GUID as string
transaction=win32transaction.OpenTransaction(0x12003F,transactions[0]) #got the first parameter from https://github.com/mhammond/pywin32/blob/bd6b7f9ad54c2ce268674eab2b74dce625fb13dd/win32/Lib/winnt.py
#error: pywintypes.error: (6715, 'OpenTransaction',...'Could not find transaction object') 
win32file.CancelIo(transaction) #not reached, can't tell if it would work
p.terminate() #doesn't work, process is un-killable

正如我所评论的,当前代码无法在主 python 进程中检索事务句柄,因为它说它找不到事务对象。我不得不走GUID的方式,因为python不能直接腌制PyHANDLE对象。因此,解决方案是一种在进程之间传递对象的方法。另一方面,我非常怀疑仅此一项就是它失败的原因。我也可以使用任何允许我在预定时间后取消复制操作的解决方案。 我还尝试了通过设置传递给 CopyFileExW 的全局变量来通知的解决方案,该变量由 @Eryk Sun 和 @DrakeWu-MSFT 提出,但这也没有取消操作。

reason这里是回调 CopyProgressRoutine 中的一个参数。 0 表示复制了数据文件的另一部分,1 表示已创建另一个流,即将复制。这是首次调用回调例程时给出的回调原因。

debug_programs的每个参数对应文档中回调函数的参数。

判断StreamBytesTransferred与之前回调中的值相比是否有变化,并dwCallbackReason == 0,然后决定返回PROGRESS_CANCEL

如果回调函数也在阻塞,我怀疑问题不在文件 I/O 上,但内部可能存在死锁。也许您应该先尝试读取文件,然后写入新文件(如果文件可读(。

相关内容

  • 没有找到相关文章

最新更新