<p>Python捕获自己的异常、大多数信号和exit(),然后运行<code>atexit</code>例程进行清理。所以,你可以在那里处理正常的坏习惯。你知道吗</p>
<p>但也有其他不好的事情发生。分段错误或其它内部错误。未知信号。调用<code>os._exit()</code>的代码。这将导致提前终止,并且尚未刷新的数据将丢失。任何程序都可能发生不好的事情,如果它们需要额外的恢复能力,它们需要一些方法来处理。你知道吗</p>
<ul>
<li><p>您可以将内容写入临时文件,并仅在完成后将其重命名为“活动”文件。如果程序终止,至少它最后保存的数据仍然存在。</p></li>
<li><p>您可以编写更改日志或日志,并通过扫描该日志来重建所需的数据。这就是许多文件系统的工作原理,“大数据”将系统映射/简化为基本相同的东西。</p></li>
<li><p>您可以移动到数据库并使用它的事务处理或任何OLPT系统来确保您对数据存储进行全部或全部更新。</p></li>
</ul>
<p>您的示例代码特别脆弱,因为</p>
<pre><code>data = open('DisCoin.json','wb')
</code></pre>
<p>清除磁盘上的现有数据。用这个密码是不可能回去的!那么,第一步就是不要那样做。保留旧数据,直到新数据准备好。你知道吗</p>
<p>下面是一个为您管理临时文件的示例类。使用它而不是<code>open</code>,它将创建一个临时文件供您更新,并且只使用<code>with</code>子句的数据运行,没有异常。如果在<code>with</code>子句中使用atexit处理程序,则不需要它。你知道吗</p>
<pre><code>import shutil
import os
class SidelineFile:
def __init__(self, *args, **kw):
self.args = list(args)
self.kw = kw
def __enter__(self):
self.closed = False
self.orig_filename = self.args[0]
self.args[0] += '.tmp'
try:
mode = self.args[1]
except IndexError:
try:
mode = self.kw['mode']
except KeyError:
mode = 'r'
if 'a' in mode:
shutil.copy2(self.orig_filename, self.args[0])
self.file_obj = open(*self.args, **self.kw)
return self.file_obj
def __exit__(self, exc_type, exc_value, traceback):
if not self.closed:
self.file_obj.close()
self.closed = True
if not exc_type:
os.rename(self.args[0], self.orig_filename)
else:
os.remove(self.args[0])
fn = 'test.txt'
with SidelineFile(fn, 'w') as fp:
fp.write("foo")
print(1, repr(open(fn).read()))
with SidelineFile(fn, mode='a') as fp:
fp.write("bar")
print(2, repr(open(fn).read()))
with SidelineFile(fn, 'w') as fp:
fp.write("foo")
print(3, repr(open(fn).read()))
try:
with SidelineFile(fn, 'a') as fp:
fp.write("bar")
raise IndexError()
except IndexError:
pass
print(4, repr(open(fn).read()))
</code></pre>