python 文件操作不被打断_如何防止代码块被Python中的KeyboardInterrupt中断?

如何防止代码块被Python中的KeyboardInterrupt中断?

我正在写一个程序,通过pickle模块缓存一些结果。 目前发生的情况是,如果我在dump操作发生时按ctrl-c,则dump会被打断并且结果文件被损坏(即仅部分写入,因此无法再次loaded)。

有没有办法使dump或通常的代码块不间断? 我当前的解决方法如下所示:

try:

file = open(path, 'w')

dump(obj, file)

file.close()

except KeyboardInterrupt:

file.close()

file.open(path,'w')

dump(obj, file)

file.close()

raise

如果该操作被中断,重新启动该操作似乎很愚蠢,所以我正在寻找推迟该中断的方法。 我该怎么做呢?

saffsd asked 2020-02-06T03:57:26Z

5个解决方案

60 votes

以下是上下文管理器,它为SIGINT附加了信号处理程序。如果调用了上下文管理器的信号处理程序,则在上下文管理器退出时仅通过将信号传递给原始处理程序来延迟信号。

import signal

import logging

class DelayedKeyboardInterrupt(object):

def __enter__(self):

self.signal_received = False

self.old_handler = signal.signal(signal.SIGINT, self.handler)

def handler(self, sig, frame):

self.signal_received = (sig, frame)

logging.debug('SIGINT received. Delaying KeyboardInterrupt.')

def __exit__(self, type, value, traceback):

signal.signal(signal.SIGINT, self.old_handler)

if self.signal_received:

self.old_handler(*self.signal_received)

with DelayedKeyboardInterrupt():

# stuff here will not be interrupted by SIGINT

critical_code()

Gary van der Merwe answered 2020-02-06T03:58:40Z

40 votes

将函数放在线程中,然后等待线程完成。

除非使用特殊的C api,否则无法中断Python线程。

import time

from threading import Thread

def noInterrupt():

for i in xrange(4):

print i

time.sleep(1)

a = Thread(target=noInterrupt)

a.start()

a.join()

print "done"

0

1

2

3

Traceback (most recent call last):

File "C:\Users\Admin\Desktop\test.py", line 11, in

a.join()

File "C:\Python26\lib\threading.py", line 634, in join

self.__block.wait()

File "C:\Python26\lib\threading.py", line 237, in wait

waiter.acquire()

KeyboardInterrupt

看到中断如何推迟到线程完成为止?

在这里它适合您的使用:

import time

from threading import Thread

def noInterrupt(path, obj):

try:

file = open(path, 'w')

dump(obj, file)

finally:

file.close()

a = Thread(target=noInterrupt, args=(path,obj))

a.start()

a.join()

Unknown answered 2020-02-06T03:58:20Z

25 votes

在此过程中,使用信号模块禁用SIGINT:

s = signal.signal(signal.SIGINT, signal.SIG_IGN)

do_important_stuff()

signal.signal(signal.SIGINT, s)

Ignacio Vazquez-Abrams answered 2020-02-06T03:59:01Z

10 votes

我认为为此使用线程是过大的。 您可以通过简单地循环执行直到成功写入来确保正确保存了文件:

def saveToFile(obj, filename):

file = open(filename, 'w')

cPickle.dump(obj, file)

file.close()

return True

done = False

while not done:

try:

done = saveToFile(obj, 'file')

except KeyboardInterrupt:

print 'retry'

continue

Nadia Alramli answered 2020-02-06T03:59:21Z

1 votes

这个问题是关于阻止pip install atomicwrites的,但是对于这种情况,我发现原子文件写入更加简洁并提供了额外的保护。

使用原子写入,可以正确地写入整个文件,或者不执行任何操作。 Stackoverflow有多种解决方案,但个人而言,我只喜欢使用atomicwrites库。

运行pip install atomicwrites之后,只需像这样使用它:

from atomicwrites import atomic_write

with atomic_write(path, overwrite=True) as file:

dump(obj, file)

Chris answered 2020-02-06T03:59:50Z

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值