在 Python 3.6 中,长 运行 循环如何导致变量变为未定义?
In Python 3.6, how could a long running loop cause a variable to become undefined?
简短版本:
我有一个嵌套循环,当它 运行s 的时间比正常情况(2 小时)长时,某些原因导致变量仅在该内部循环内变为未定义。外循环可以毫无问题地使用它。
长版:
我在 RHEL 机器上有一个 Python 3.6 脚本 运行ning,它从 SQL 服务器中提取表格,一次 500,000 行,并将它们写入 .csv 文件,然后被处理到不同的数据库中。
我首先在 Class 中建立与源和目标的连接,以便会话持续存在并为每个操作重复使用。我有心跳查询 运行 在我 运行 循环时保持其他非活动会话处于活动状态。 (未显示,但目前仅在外循环中 - 这很快就会改变)
该框架相当简单...我将源表列表从文件读取到数据框中。然后,代码是(删除了内部循环中的一些代码,但保留了解释正在发生的事情的注释)。 :
for index, row in tables_to_load.iterrows():
#try to load all new rows into target
try:
table_name = tables_to_load['Source_Table'][index]
pk = tables_to_load['pk'][index]
odsstage_table_name = tables_to_load['ODSSTAGE_Table'][index]
ods_table_name = tables_to_load['ODS_Table'][index]
last_loaded_lsn = sf_ods.get_last_loaded_lsn(table_name)
max_lsn = source.get_max_lsn(table_name)
# Get the number of rows to load
incr_count = source.get_incr_count(table_name, pk, last_loaded_lsn)
total_process_rows = total_process_rows + incr_count
#WORKS FINE EVERY TIME
file.write("There are " + str(incr_count) + " rows to be loaded for the table: " + table_name + "\n\n")
# Set up your offset limits
offset_iterator = 0 # Start at the 1st row of the increment
fetch_count = 500000 # Increment by 500k rows.
if incr_count == 0: #only run if there are new rows to load to target
status = "No Rows To Load"
else: # If there are rows to load, proceed loading them to target
try:
inc_write_success = 1
# Begin looping through the increment in source until offset_iterator > the number of rows in the increment
while offset_iterator < incr_count:
sf_dw.heartbeat()
#ERROR OCCURS HERE
file.write(table_name + ": Loading the next " + str(fetch_count) + " rows starting at row " + str(offset_iterator + 1) + " out of " + str(incr_count) + " rows" + "\n")
# Get the incremental dataframe starting at the offset_indicator row
#the df is the first object returned
#the list of columns in the original table is the third object returned
# Write the dataframe to a compressed file at the temporary storage
# Move the file to target and COPY INTO the ODSSTAGE table in target
# Merge ODSSTAGE to ODS
# Update the offset_iterator to fetch the next increment of rows until you've reached the max_lsn
offset_iterator += fetch_count
except Exception as e:
any_errors = True
inc_write_success = 0
# Update log_cdc table
try:
if inc_write_success == 1:
#WORKS FINE
sf_ods.update_last_loaded_lsn(table_name, max_lsn, status)
else:
#WORKS FINE
file.write("Unable to Update Max_LSN for " + table_name + " due to increment failure. \n")
except Exception as e:
file.write(str(e) + "\n")
except Exception as e:
file.write(str(e) + "\n")
inc_write_success = 0
stop_table_load = datetime.datetime.now()
load_table_time = stop_table_load - table_load_start
#AGAIN WORKS FINE
file.write("Finished loading " + table_name + ". Load Time: " + str(load_table_time) + "\n")
问题:每当内部循环需要超过 4 小时才能完成时,下一个 'for' 实例似乎可以很好地处理一切,直到内部循环的第一个 运行,我在那里受到欢迎与“名称 'table_name' 未定义”。据我所知,它似乎发生在指定的位置,我正在为日志文件填写一些行。日志文件中有几行表明 table_name 变量在调用内部循环之前和之后都正常运行。
该变量未定义为全局...它是在尝试时定义的。
我应该将其创建为全局变量吗?在内部循环中重命名它?
我无权 post 关于该项目的任何更具体的内容。
我不相信程序在您建议的地方失败了,至少单独看这个片段是这样。
我猜 table_name = tables_to_load['Source_Table'][index]
实际上失败了。如果失败,table_name
将永远不会被定义;您的代码将跳转到您的外部 except
语句并使用 inc_write_success 内容写入文件。然后它将尝试执行
file.write("Finished loading " + table_name + ". Load Time: " + str(load_table_time) + "\n")
并在那里失败。
提供显示错误发生位置的堆栈跟踪在这些情况下也很有帮助。
简短版本: 我有一个嵌套循环,当它 运行s 的时间比正常情况(2 小时)长时,某些原因导致变量仅在该内部循环内变为未定义。外循环可以毫无问题地使用它。
长版: 我在 RHEL 机器上有一个 Python 3.6 脚本 运行ning,它从 SQL 服务器中提取表格,一次 500,000 行,并将它们写入 .csv 文件,然后被处理到不同的数据库中。
我首先在 Class 中建立与源和目标的连接,以便会话持续存在并为每个操作重复使用。我有心跳查询 运行 在我 运行 循环时保持其他非活动会话处于活动状态。 (未显示,但目前仅在外循环中 - 这很快就会改变)
该框架相当简单...我将源表列表从文件读取到数据框中。然后,代码是(删除了内部循环中的一些代码,但保留了解释正在发生的事情的注释)。 :
for index, row in tables_to_load.iterrows():
#try to load all new rows into target
try:
table_name = tables_to_load['Source_Table'][index]
pk = tables_to_load['pk'][index]
odsstage_table_name = tables_to_load['ODSSTAGE_Table'][index]
ods_table_name = tables_to_load['ODS_Table'][index]
last_loaded_lsn = sf_ods.get_last_loaded_lsn(table_name)
max_lsn = source.get_max_lsn(table_name)
# Get the number of rows to load
incr_count = source.get_incr_count(table_name, pk, last_loaded_lsn)
total_process_rows = total_process_rows + incr_count
#WORKS FINE EVERY TIME
file.write("There are " + str(incr_count) + " rows to be loaded for the table: " + table_name + "\n\n")
# Set up your offset limits
offset_iterator = 0 # Start at the 1st row of the increment
fetch_count = 500000 # Increment by 500k rows.
if incr_count == 0: #only run if there are new rows to load to target
status = "No Rows To Load"
else: # If there are rows to load, proceed loading them to target
try:
inc_write_success = 1
# Begin looping through the increment in source until offset_iterator > the number of rows in the increment
while offset_iterator < incr_count:
sf_dw.heartbeat()
#ERROR OCCURS HERE
file.write(table_name + ": Loading the next " + str(fetch_count) + " rows starting at row " + str(offset_iterator + 1) + " out of " + str(incr_count) + " rows" + "\n")
# Get the incremental dataframe starting at the offset_indicator row
#the df is the first object returned
#the list of columns in the original table is the third object returned
# Write the dataframe to a compressed file at the temporary storage
# Move the file to target and COPY INTO the ODSSTAGE table in target
# Merge ODSSTAGE to ODS
# Update the offset_iterator to fetch the next increment of rows until you've reached the max_lsn
offset_iterator += fetch_count
except Exception as e:
any_errors = True
inc_write_success = 0
# Update log_cdc table
try:
if inc_write_success == 1:
#WORKS FINE
sf_ods.update_last_loaded_lsn(table_name, max_lsn, status)
else:
#WORKS FINE
file.write("Unable to Update Max_LSN for " + table_name + " due to increment failure. \n")
except Exception as e:
file.write(str(e) + "\n")
except Exception as e:
file.write(str(e) + "\n")
inc_write_success = 0
stop_table_load = datetime.datetime.now()
load_table_time = stop_table_load - table_load_start
#AGAIN WORKS FINE
file.write("Finished loading " + table_name + ". Load Time: " + str(load_table_time) + "\n")
问题:每当内部循环需要超过 4 小时才能完成时,下一个 'for' 实例似乎可以很好地处理一切,直到内部循环的第一个 运行,我在那里受到欢迎与“名称 'table_name' 未定义”。据我所知,它似乎发生在指定的位置,我正在为日志文件填写一些行。日志文件中有几行表明 table_name 变量在调用内部循环之前和之后都正常运行。
该变量未定义为全局...它是在尝试时定义的。
我应该将其创建为全局变量吗?在内部循环中重命名它?
我无权 post 关于该项目的任何更具体的内容。
我不相信程序在您建议的地方失败了,至少单独看这个片段是这样。
我猜 table_name = tables_to_load['Source_Table'][index]
实际上失败了。如果失败,table_name
将永远不会被定义;您的代码将跳转到您的外部 except
语句并使用 inc_write_success 内容写入文件。然后它将尝试执行
file.write("Finished loading " + table_name + ". Load Time: " + str(load_table_time) + "\n")
并在那里失败。
提供显示错误发生位置的堆栈跟踪在这些情况下也很有帮助。