我正在使用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时仅 重新启动,而在脚本成功完成后绝对不希望重新启动。因此,在此示例中,它根本不应该重新启动,因为脚本在第一次运行时应该成功。我事先知道要处理多少个文件,所以我知道脚本到达最后一个文件时已成功完成。
答案 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
包装在函数中for
循环,为每个文件调用一次函数for
循环包装到无限while
循环中,直到所有文件都被
已处理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。