【问题标题】:Python restoring an interrupt iteration of two listsPython恢复两个列表的中断迭代
【发布时间】:2015-12-22 17:08:16
【问题描述】:

代码如下:

import itertools
# import list from file
a = [line.strip() for line in open("real.txt", 'r')]
b = [line.strip() for line in open("imag.txt", 'r')]

# create file contain restore informations 
f = open("restore.txt","w+")
loop = 0
try:
    for r in itertools.product(a,b):
         loop +=1
         print "processing : "+ r[1] + ": "+ r[0] + "  ("+str(loop)+")"

except Exception, e:
    print str(e)
    f.write("iterazions seccession: " +str(loop)+"\n")
    f.write("real number : " +r[1]+"\n")
    f.write("imaginary unit: " + r[0]+ "\n")

示例输出

processing: 1 : 1i (1)
processing: 1 : 2i (2)
processing: 1 : 3i (3)
processing: 1 : 4i (4)
...
processing: 2000 : 174i (348000)
processing: 2000 : 175i (348001)
...and so forth
(it does all combinations of two lists)

问题是如果错误停止迭代,有没有办法从上一次迭代重新启动脚本而不从头开始? 我尝试将最后一个值保存在文件中,但我不知道如何使用它。

附言我知道复数的 cmath 函数,但我更感兴趣的是恢复问题

更具体

如果出现错误,则在以下位置停止迭代: 处理:2000:175i (348001) 有没有办法从 2000 : 175i (348001) 迭代重新启动脚本?

【问题讨论】:

  • 我不太明白你的问题是什么。请举一个错误会停止的例子。
  • 任何可能停止迭代的错误。

标签: python iteration pickle


【解决方案1】:

将 try/except 放在 for 循环中 - 如果 except 没有引发,则 for 循环将继续。

for r in itertools.product(a,b):
    try:
         loop +=1
         print "processing : "+ r[1] + ": "+ r[0] + "  ("+str(loop)+")"
             #enable for testing error
             #if loop == 15:
                 #loop = loop/0
    except Exception, e:
        print str(e)
        f.write("iterazions seccession: " +str(loop)+"\n")
        f.write("real number : " +r[1]+"\n")
        f.write("imaginary unit: " + r[0]+ "\n")

【讨论】:

  • 谢谢。但是是否可以在不从头开始的情况下恢复中断的会话?
  • 自动,没有。如果您编写的代码保存当前状态并且(可选地)在重新启动时使用保存的当前状态,那么是的,一般来说,虽然我不知道是否可以恢复 itertools.product - 基本上你将不得不实现任何需要做简历。
【解决方案2】:

通常您会看到try ... except 块的使用,这在 Python 中相对便宜。

这不会停止循环的执行,如本例所示(可应用于您的情况):

numbers = [1, 3, 2, 5, 0, 4, 5]

for number in numbers:
  try:
    print(10/number)
  except ZeroDivisionError:
    print("Please don't divide by 0...")

您将在 Python 2.7.11 中看到对此的输出:

10
3
5
2
Please don't divide by 0...
2
2

如果您的代码可以抛出多种类型的异常,您可以将它们链接起来:

numbers = [1, 3, 2, 5, 0, 4, 5]

for number in numbers:
  try:
    print(10/number)
  except ZeroDivisionError:
    print("Please don't divide by 0...")
  except ValueError:
    print("Something something ValueError")
  except KeyError:
    print("Something something KeyError")

如果您知道代码可能引发的所有异常类型,则可以适当地处理它们,这通常是比一般异常解决方案更好的解决方案。


关于您的代码的一般说明:

为变量使用更具代表性的名称

  • 使用更具代表性的名称将帮助用户/维护者了解您的代码发生了什么帮助您发现错误。 ab 在实数和虚数方面意义不大 - 为什么不使用 real_numsimag_nums?没有更多的打字和更多的描述性。

使用open(file) as f

  • 这将自动关闭您的文件,因此您以后无需担心,这可能会给写入/附加带来问题

使用enumerate(iterable)

  • 这将跟踪迭代次数和迭代中的对象

遍历元组

  • 您无需使用 [] 表示法进行访问 - 您可以直接使用元组中的元素。

使用格式字符串

  • 这些将使您的代码在打印时看起来更漂亮

把所有这些放在一起:

import itertools
# import list from file

reals = [line.strip() for line in open("real.txt", 'r')]
imags = [line.strip() for line in open("imag.txt", 'r')]

# create file contain restore informations 
with open("restore.txt", "w+") as f:
    for i, (real, imag) in enumerate(itertools.product(reals, imags)):
        try:
            print "processing: {0}, {1}, ({2})".format(real, imag, i) 
            # Process data here

            #enable for testing error
            if i == 15:
                i = i/0
        except ZeroDivisionError:
            # Handle exception here
            continue
        except Exception as e:
            print str(e)
            f.write("iterazions seccession: {0}\n".format(i))
            f.write("real number: {0}\n".format(real))
            f.write("imaginary unit: {0}\n".format(imag))

【讨论】:

  • 通常你会想知道什么类型的异常 - 否则它会让编码器看起来很粗心。您可以删除ZeroDivisionError,它仍然可以工作,但您不会获得有关导致异常的原因的任何信息。
  • 好的。但如果错误停止代码,有办法在最后一点处理时重新启动它吗?
  • 我想我还是不明白你在问什么......这不会停止你的处理。
  • 对不起...尝试用另一种方式解释它。如果我想暂停脚本并重新启动?有可能吗?
  • 听起来我们正在解决 XY 问题的 X 问题。
【解决方案3】:

我的解决方案

所以,我的问题是“如何在不从头开始的情况下从上次迭代中重新启动脚本?”。 首先,我尝试使用hard way,即使它运行良好,我也意识到一种比这更简单的方法(亲亲对不对?)。代码如下:

import itertools
import pickle  #for restoring last data session
fname = "restore.pck"

reals = [line.strip() for line in open("real.txt", 'r')]
imags = [line.strip() for line in open("imag.txt", 'r')]

seed_count = 0 #number last processing cycle
count_ses = 0  #number current session cycle
count_tot = 0  #number total cycle processing so far
it_tot=len(reals)*len(imgs)

ret = raw_input("recover last session?: y/n")
if ret =="y":
    with open(fname,"rb") as f:
        rec= pickle.load(f)
        print  "last session data {0} {1} {2}".format(rec[0],rec[1],rec[2])
        seed_count=rec[2]
        seed_img=rec[1]
        seed_rea=rec[0]
try:
 print "total iterations", it_tot

 for r in itertools.product(reals,imgs):
    # do nothing until you get last interrupted cycle
    count_tot+=1
    if count_tot >= seed_count:
    # and now start processing
     count_ses +=1
     print "processing: {0}, {1}, (total : {2}), (this session: {3}) {4}% )".format(r[0], r[1], count_tot, count_ses,(count_tot/len_tot*100))

except Exception as e:
    print str(e)
    #save data if an error occurred
    store = r[0], r[1], count_tot
    with open(fname,"wb") as f:
     pickle.dump(store,f,pickle.HIGHEST_PROTOCOL)
     f.close()

它只是让迭代运行而不处理任何东西,直到它到达最后一个处理周期,然后重新开始计算。 当然有些“聪明人”会说这不是pythonic的方式这个代码很乱,不像我的那样花哨但这是我的第一个python程序,它可以工作我很高兴:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-01
    • 2019-11-28
    • 2014-02-15
    • 2015-01-17
    • 2013-05-23
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    相关资源
    最近更新 更多