python-如果程序崩溃,如何恢复FOR循环?

python-如果程序崩溃,如何恢复FOR循环?,python,for-loop,Python,For Loop,此程序非常依赖于网络,有时网络会崩溃 有一种方法可以恢复“for循环”,以防程序崩溃,下次我启动程序时,它将在程序崩溃的同一用户中启动 守则: users = [ {'username': 'user1', 'email': 'mail1@mail.com'}, {'username': 'user2', 'email': 'mail2@mail.com'}, {'username': 'user3', 'email': 'mai

此程序非常依赖于网络,有时网络会崩溃

有一种方法可以恢复“for循环”,以防程序崩溃,下次我启动程序时,它将在程序崩溃的同一用户中启动

守则:

users = [
           {'username': 'user1', 'email': 'mail1@mail.com'},
           {'username': 'user2', 'email': 'mail2@mail.com'},
           {'username': 'user3', 'email': 'mail3@mail.com'},
           {'username': 'user4', 'email': 'mail4@mail.com'},
        ]

try:
    text_file = open("current_username.txt", "w")

    for item in users:
        text_file.seek(0)
        text_file.truncate()
        text_file.write(item['username'])
        # BEGIN, some relevant code that sometimes crashes and don't is code dependent
        # ...
        # END, some relevant code that sometimes crashes and don't is code dependent

    text_file.close()
except:
    text_file.close()

关于我下次启动程序时如何启动的线索,它将在导致代码崩溃的同一个“用户名”上启动吗?

这取决于恢复的关键程度

对于一种简单、非关键的方法,使用上下文管理器和
with
语句将更好地处理异常,并使您的初始
写入(用户名)
更可能写入文件,以便您可以使用它来恢复当前用户:

with open("current_username.txt", "w") as text_file:
    for item in users:
        text_file.seek(0)
        ...
带有的
将在文件退出或出现异常时关闭文件并释放资源

对于恢复,您可以使用
itertools.takewhile()
,例如(伪代码),为当前用户使用迭代器:


这确实取决于恢复的关键程度

对于一种简单、非关键的方法,使用上下文管理器和
with
语句将更好地处理异常,并使您的初始
写入(用户名)
更可能写入文件,以便您可以使用它来恢复当前用户:

with open("current_username.txt", "w") as text_file:
    for item in users:
        text_file.seek(0)
        ...
带有
将在文件退出或出现异常时关闭文件并释放资源

对于恢复,您可以使用
itertools.takewhile()
,例如(伪代码),为当前用户使用迭代器:


如果崩溃不依赖于代码,我建议使用索引进行不同的迭代,然后将该索引存储在硬盘中。 我不是这个解决方案的真正粉丝,但这可能是您想要的:

users = [
       {1:{'username': 'user1', 'email': 'mail1@mail.com'}},
       {2:{'username': 'user2', 'email': 'mail2@mail.com'}},
       {3:{'username': 'user3', 'email': 'mail3@mail.com'}},
       {4:{'username': 'user4', 'email': 'mail4@mail.com'}},
    ]
counter = 0
try:
    saveFile = open('saveFile.txt','r')
    counter = int(saveFile.read())
    saveFile.close()
except IOError:
    pass

try:
    text_file = open("current_username.txt", "w")
    for i in range(counter,len(users)):
        item = users[i]
        text_file.seek(0)
        text_file.truncate()
        text_file.write(item['username'])
        # BEGIN, some relevant code that sometimes crashes and don't is     code dependent
        # ...
        # END, some relevant code that sometimes crashes and don't is code dependent
        counter = i
    text_file.close()
except:
    saveFile = open('savefile.txt','w+')
    saveFile.write(counter)
    saveFile.close()
    text_file.close()

尽管如此,如果在处理数据时发生崩溃,这也不会节省您的时间,因为操作不是原子操作。当您完成对
项的处理时,会保存进度,因此我认为您可能会有重复的数据。

如果您的崩溃与代码无关,我建议使用索引进行不同的迭代,然后将此索引存储在硬盘中。 我不是这个解决方案的真正粉丝,但这可能是您想要的:

users = [
       {1:{'username': 'user1', 'email': 'mail1@mail.com'}},
       {2:{'username': 'user2', 'email': 'mail2@mail.com'}},
       {3:{'username': 'user3', 'email': 'mail3@mail.com'}},
       {4:{'username': 'user4', 'email': 'mail4@mail.com'}},
    ]
counter = 0
try:
    saveFile = open('saveFile.txt','r')
    counter = int(saveFile.read())
    saveFile.close()
except IOError:
    pass

try:
    text_file = open("current_username.txt", "w")
    for i in range(counter,len(users)):
        item = users[i]
        text_file.seek(0)
        text_file.truncate()
        text_file.write(item['username'])
        # BEGIN, some relevant code that sometimes crashes and don't is     code dependent
        # ...
        # END, some relevant code that sometimes crashes and don't is code dependent
        counter = i
    text_file.close()
except:
    saveFile = open('savefile.txt','w+')
    saveFile.write(counter)
    saveFile.close()
    text_file.close()

尽管如此,如果在处理数据时发生崩溃,这也不会节省您的时间,因为操作不是原子操作。当您完成对
项的处理时,进度会被保存下来,因此我认为您可能会有重复的数据。

最简单的方法可能是将
for
循环中的内容包装到另一个循环中,并仅在成功时退出。此外,您可能希望将with
与as
构造一起使用

with open("current_username.txt", "w") as text_file:

    for item in users:
        text_file.seek(0)
        text_file.truncate()
        text_file.write(item['username'])

        while True:
            try:
                # BEGIN, some relevant code that sometimes crashes and don't is code dependent
                # ...
                # END, some relevant code that sometimes crashes and don't is code dependent
            except: # Should probably specify a specific error type
                # Possibly undo changes made above
                pass
            else:
                break

# text_file is automatically closed when the `with` block is exited

最简单的方法可能是将
for
循环中的内容包装到另一个循环中,并仅在成功时退出。此外,您可能希望将with
与as
构造一起使用

with open("current_username.txt", "w") as text_file:

    for item in users:
        text_file.seek(0)
        text_file.truncate()
        text_file.write(item['username'])

        while True:
            try:
                # BEGIN, some relevant code that sometimes crashes and don't is code dependent
                # ...
                # END, some relevant code that sometimes crashes and don't is code dependent
            except: # Should probably specify a specific error type
                # Possibly undo changes made above
                pass
            else:
                break

# text_file is automatically closed when the `with` block is exited
我建议你试试。这是序列化对象的最简单方法,可用于保存状态

您可以执行以下操作来恢复循环:

import pickle

'''
Your other code here
'''
global REGISTRY    
start = pickle.loads(REGISTRY) if REGISTRY else 0
for i in xrange(start, len(users)):
    text_file.seek(0)
    text_file.truncate()
    text_file.write(item['username'])
    REGISTRY = pickle.dumps(i)
我建议你试试。这是序列化对象的最简单方法,可用于保存状态

您可以执行以下操作来恢复循环:

import pickle

'''
Your other code here
'''
global REGISTRY    
start = pickle.loads(REGISTRY) if REGISTRY else 0
for i in xrange(start, len(users)):
    text_file.seek(0)
    text_file.truncate()
    text_file.write(item['username'])
    REGISTRY = pickle.dumps(i)

使用相同的代码并进行了一些调整

users = [
           {'username': 'user1', 'email': 'mail1@mail.com'},
           {'username': 'user2', 'email': 'mail2@mail.com'},
           {'username': 'user3', 'email': 'mail3@mail.com'},
           {'username': 'user4', 'email': 'mail4@mail.com'},
        ]

try:
    #Open file to Read / Write, note the 'r+'
    text_file = open("current_username.txt", "r+")
    text_file.seek(0)

    #Read the last user written in the file
    current_user = text_file.readline()
    last_index = 0

    if current_user is not '':
        for last in range(len(users)):
            if users[last]['username'] == current_user:
                last_index = last
                break

    for index in range(last_index, len(users)):
        text_file.seek(0)
        text_file.truncate()
        text_file.write(users[index]['username'])
        print(users[index])

        # BEGIN, some relevant code that sometimes crashes and don't is code dependent
        # ...
        # END, some relevant code that sometimes crashes and don't is code dependent

    text_file.seek(0)
    text_file.truncate()
    text_file.write('')
    text_file.close()

except Exception as e:
    print(e)
    text_file.close()

如果循环结束异常,则当前用户名.txt拥有最后一个用户,而第一个循环寻找最后一个索引并从那里开始,另一方面,如果当前用户名.txt没有任何数据,则下一个程序从开始执行。

使用相同的代码并进行一些调整

users = [
           {'username': 'user1', 'email': 'mail1@mail.com'},
           {'username': 'user2', 'email': 'mail2@mail.com'},
           {'username': 'user3', 'email': 'mail3@mail.com'},
           {'username': 'user4', 'email': 'mail4@mail.com'},
        ]

try:
    #Open file to Read / Write, note the 'r+'
    text_file = open("current_username.txt", "r+")
    text_file.seek(0)

    #Read the last user written in the file
    current_user = text_file.readline()
    last_index = 0

    if current_user is not '':
        for last in range(len(users)):
            if users[last]['username'] == current_user:
                last_index = last
                break

    for index in range(last_index, len(users)):
        text_file.seek(0)
        text_file.truncate()
        text_file.write(users[index]['username'])
        print(users[index])

        # BEGIN, some relevant code that sometimes crashes and don't is code dependent
        # ...
        # END, some relevant code that sometimes crashes and don't is code dependent

    text_file.seek(0)
    text_file.truncate()
    text_file.write('')
    text_file.close()

except Exception as e:
    print(e)
    text_file.close()

如果循环异常结束,则
current_username.txt
拥有最后一个用户,而第一个循环寻找最后一个索引并从那里开始,另一方面,如果
current_username.txt
没有任何数据,下一个程序从一开始就开始执行。

显示如何以确保不会出现部分内容(或在意外崩溃时不会为空&c)的方式写入该文件是完成此答案的一个重要元素。相关:演示如何编写该文件,以确保不会出现部分内容(或在意外崩溃时不会为空&c)是完成此答案的一个重要元素。相关:当您
打开('savefile.txt','w+')
,这将截断原始内容。此时的崩溃将使计数器完全清空。因此,这不是一种安全的原子文件更新方法。我打算擦除计数器的进度,因为每次保存新计数器时,我都需要覆盖它。但问题是,当文件暂时为空时,您会有一个瞬间,因此如果在错误的时间拔出电源(或您收到SIGKILL),程序的下一次调用不会在该调用停止的地方重新启动。还有其他更好的方法来替换没有此问题的文件内容。请参阅我在AChampion对答案的评论中发布的链接。
打开('savefile.txt','w+')
时,会截断原始内容。此时的崩溃将使计数器完全清空。因此,这不是一种安全的原子文件更新方法。我打算擦除计数器的进度,因为每次保存新计数器时,我都需要覆盖它。但问题是,当文件暂时为空时,您会有一个瞬间,因此如果在错误的时间拔出电源(或您收到SIGKILL),程序的下一次调用不会在该调用停止的地方重新启动。还有其他更好的方法来替换没有此问题的文件内容。请参阅我在AChampion对答案的评论中发布的链接。如果您在
truncate()
write()
之间受到电源猛拉或SIGKILL,我们将回到起点。您需要调用
flush()
,以确保写入操作能够及时执行。没错,我更关注的是如何优雅地处理(软战争)