arcpy错误后重新启动python脚本,直到成功

时间:2018-06-20 23:33:14

标签: python python-2.7 arcgis arcpy

我正在使用Python(2.7)中的ArcGIS的arcpy模块,使用许多不同的工具来处理许多多边形shapefile。每隔一段时间它就会抛出一个随机错误,我会捕获一个异常,但是随后所有的shapefile都会受到相同错误的影响。我真的不明白是什么导致了此错误(错误010088),我唯一的解决方法是从成功处理的最后一个文件重新启动脚本。

我的问题是:每次遇到此错误时,如何重新启动脚本,然后在成功处理所有文件后停止?

我看过各种不同的问题(例如Restarting a self-updating python script),但工作无济于事,或者因为我仍然是一名Python初学者,所以我不明白如何将其应用于我的情况。根据此博客文章,我最接近的是以下示例:https://www.alexkras.com/how-to-restart-python-script-after-exception-and-run-it-forever/

名为test.py的脚本:

import arcpy
import sys

try:
    arcpy.Buffer_analysis(r"E:\temp\boundary.shp",
                          r"E:\temp\boundary2.shp",
                          "100 Feet")
# Print arcpy execute error
except arcpy.ExecuteError as e:
    # Print
    print(e)
# Pass any other type of error
except:
    pass

在同一目录中名为forever.py的脚本:

from subprocess import Popen
import sys

filename = sys.argv[1]
while True:
    print("\nStarting " + filename)
    p = Popen("python " + filename, shell=True)
    p.wait()

(请注意boundary.shp只是一个随机边界多边形-在此处可用:https://drive.google.com/open?id=1LylBm7ABQoSdxKng59rsT4zAQn4cxv7a)。

我在Windows计算机上,因此我在命令行中使用以下命令运行所有这些操作:

python.exe forever.py test.py

按预期,此脚本首次运行时没有错误,此后由于输出文件已存在而出现错误(错误000725)。问题在于,最终我希望脚本在出现错误010088时仅 重新启动,而在脚本成功完成后绝对不希望重新启动。因此,在此示例中,它根本不应该重新启动,因为脚本在第一次运行时应该成功。我事先知道要处理多少个文件,所以我知道脚本到达最后一个文件时已成功完成。

2 个答案:

答案 0 :(得分:1)

要回答您的问题

force restart没有循环的任何python脚本,您可以调用以下函数(在python 2.7 / windows 10上进行了测试)。

import os, sys

def force_restart_script():
    python = sys.executable
    os.execl(python, python, * sys.argv)

但是

由于您使用批处理调用python脚本,因此问题的答案无法解决您的初始问题(经典XY-Problem)。我的建议是在python中做所有事情。如果没有理由,请不要使用批处理。

解决方案

  • test.py包装在函数中
  • 创建一个list of all input files并将其提交给函数
  • 创建一个for循环,为每个文件调用一次函数
  • 如有任何异常,请跳过文件
  • 通过调查error message string
  • 来发现错误
  • 否则,指示已处理给定文件
  • for循环包装到无限while循环中,直到所有文件都被 已处理
  • 在一个python脚本中完成所有这些操作,以便能够使用force_restart_script()函数

代码

import sys, os, arcpy
from time import sleep
# put force_restart_script() here

def arcpy_function(shapefile)       # Formerly called test.py
    try: 
       # arcpy stuff                # Your processing happens here
       return shapefile             # Return name of processed file
    except arcpy.ExecuteError as e: # In case ExecuteError:
       print(e)                     # Print error FYI
       return None                  # Return None
    except Exception as e:          # For all other errors, check message
       if 'ERROR 010088' in str(e): # restart in case of ERROR 010088
           print str(e), "hard restart"
           time.sleep(10)           # Wait so you can read what happened
           force_restart_script()   # Call the restart function
       else:                        # If not 010088, pass
           print(e)                 # Print any other error FYI
           return None              # Return None

if __name__ == "__main__":
    files_to_process = ['file1', 'file2', 'file3']       # Use glob, see link above   
    completed_files = []                                 # Processed files
    while len(completed_files) < len(files_to_process):  # Work until all are processed
        for shapefile in files_to_process:               # Process file by file
            if shapefile in completed_files:             # If the file is processed already
               os.rename(shapefile, "processed_" + shapefile)    # Rename
               continue                                  # Go to next one
            else:                                        # Otherwise
               finished_file = arcpy_function(shapefile) # Process the file
               if finished_file is not None:             # If processing worked, remember
                  completed_files.append(finished_file)
               else:                                     # If not, continue with next file
                   pass  
    else:
         print "all files processed"

请注意,如果脚本在os.rename之后被强制重新启动,则需要ERROR 010088来防止输入文件的重复处理。

此外,人们似乎在其他方面似乎也遇到了类似问题的found a workaround

答案 1 :(得分:0)

在那种情况下,我将运行一个deamon脚本,每个小脚本都执行该脚本。

import datetime
import traceback
def main():
    var filename = '/tmp/running.pid'  # a file indicate whether the script is running or not
    if os.path.isfile(filename):
        log.warning("the last script is still running perfectly, so i don't run")
        return
    else:
        try:
            with open(filename, "w") as f:
                # I choose to write the time so I can see when the script has been started.
                # you can also write the thread id like .pid file
                f.write(datetime.datetime.strftime("%Y-%m-%d %H:%M:%S"))
            run_your_script_here()  # here you run the script
        except Exception  as e:
            os.remove(filename)  # if an error occurs, delete the file so the script will be run next time in 1 minute
            log.error(e)
            log.error(traceback.format_exc())

脚本有一个缺点,如果脚本失败,则在最坏的情况下它将等待1分钟以启动下一个脚本。如果需要缩短间隔,则应在脚本中添加一些循环,并设置循环之间的时间间隔,或使用其他库,例如celery。