Reputation: 191
I know this has been asked before because I've searched around for an answer but the questions that I've read through don't really address my problem. I wrote a river warning system using Python3. Initially the script would only retrieve the data for the river closest to my house, so I decided to do a re-write or version upgrade, I suppose, so that any river could be used. Everything has been working pretty nice until I entered the Mississippi river URL and then I started getting
UnboundLocalError: local variable 'action' referenced before assignment.
Here is the code:
EDIT - Added the entire function to show where ALERT_LEVELS
is defined
def check_river(url):
ALERT_LEVELS = ["major", "moderate", "flood", "action", "low"]
headers = {"user-agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0"}
response = requests.get(url, headers=headers)
soup = BS(response.text, 'lxml')
data = []
#process the data returned from waterdata.usgs.gov
for river in soup.select("h1.data_name"):
river_name = river.get_text(strip=True)
river_data = river.find_next_sibling("div")
data.append({
"name": river_name,
"stage": river_data.select_one(".stage_stage_flow").get_text(strip=True).replace("Latest Stage: ", ""),
"flood_lvl": river_data.select_one(".flood_stage_flow").get_text(strip=True).replace("Flood Stage: ", "").replace(" Feet", ""),
"warns": river_data.select_one(".current_warns_statmnts_ads > b").next_sibling.strip(),
"alerts": {
alert_name: alert_value.get_text(strip=True)
for alert_name, alert_value in
zip(ALERT_LEVELS, river_data.select(".flood_his_lwr .box_square table tr > td:nth-of-type(2)"))
}
})
#define river data per station and set conditionals
try:
for n in range(len(data)):
station = data[n]['name']
if data[n]['stage'] == 'n/a' or data[n]['stage'] == 'Latest Flow: n/a' or data[n]['stage'] == 'Latest Stage: n/a':
if len(data[n]['alerts']) < 5:
pass
else:
stage = float(data[n]['stage'])
for a in ALERT_LEVELS:
if a in data[n]['alerts']:
action = float(data[n]['alerts']['action'])
flood = float(data[n]['alerts']['flood'])
moderate = float(data[n]['alerts']['moderate'])
major = float(data[n]['alerts']['major'])
if major == 0:
major = action
elif moderate == 0:
moderate = action
elif flood == 0:
flood == action
elif action == 0 and flood != 0:
action = flood
else:
pass
if stage < action:
pass
elif stage > major and major != 0:
print('{} stage ({}) is above [Major FLood Stage: {}]'.format(station, stage, major))
elif stage > moderate and moderate != 0:
print('{} stage ({}) is above [Moderate FLood Stage: {}]'.format(station, stage, moderate))
elif stage > flood and flood != 0:
print('{} stage ({}) is above [FLood Stage: {}]'.format(station, stage, flood))
elif stage > action and action != 0:
print('{} stage ({}) is above [Action Stage: {}]'.format(station, stage, action))
except KeyError:
raise
so then when I execute the function get_river()
here are the results:
>>> from riverwarn import get_river
>>> mississippi = 'http://water.weather.gov/ahps2/river.php?wfo=jan&wfoid=18743&riverid=203833&pt%5B%5D=all&allpoints=143846%2C142736%2C143816%2C143998%2C145144%2C142659%2C145887%2C144081%2C142375%2C143866%2C141506%2C142962%2C143885%2C153060%2C143323%2C144201%2C144542%2C142873%2C143260%2C143099%2C142560%2C144186%2C143177%2C142054%2C143945%2C144055%2C141370%2C143630%2C141931%2C142812%2C141676%2C142534%2C144568%2C143535%2C144589%2C143030%2C144031%2C143079%2C144282%2C141445%2C141722%2C141383%2C143445%2C143646%2C152882%2C143787%2C143574%2C143545%2C142773%2C141629%2C144517%2C142500%2C143196%2C142105%2C142509%2C142418%2C152996%2C152997%2C152998%2C144108%2C141463%2C152999%2C153000%2C153001%2C153002%2C152909%2C141839%2C143934%2C141618%2C146423%2C143366%2C147048%2C142172%2C151794%2C153107%2C141493%2C142940%2C144619%2C144798%2C151521%2C151430%2C144609%2C151338%2C141308%2C151468%2C144449%2C143828%2C151447%2C151342%2C142711%2C151473%2C151474%2C151475%2C151469%2C151476%2C151477%2C151448%2C151450%2C151455%2C151478%2C151451%2C151479%2C151480%2C151452&data%5B%5D=xml'
>>> sabine = 'http://water.weather.gov/ahps2/river.php?wfo=SHV&wfoid=18715&riverid=203413&pt%5B%5D=all&allpoints=143204%2C147710%2C141425%2C144668%2C141750%2C141658%2C141942%2C143491%2C144810%2C143165%2C145368&data%5B%5D=xml'
>>> redriver = 'http://water.weather.gov/ahps2/river.php?wfo=shv&wfoid=18715&riverid=204727&pt%5B%5D=all&allpoints=146209%2C142575%2C141732%2C141489%2C146261%2C146208%2C142772%2C142879%2C141588%2C142687%2C141313%2C144336%2C143593%2C141633%2C141650%2C143326%2C142421%2C143017%2C142886%2C143393%2C142504%2C141575%2C144273%2C142926%2C142145%2C144020%2C147033%2C142204%2C143687%2C142816%2C143243%2C144337%2C142619%2C142061%2C142956%2C152444%2C152443&data%5B%5D=xml'
>>> riogrande = 'http://water.weather.gov/ahps2/river.php?wfo=crp&wfoid=18767&riverid=204592&pt%5B%5D=all&allpoints=144166%2C144467%2C143214%2C143547%2C142661%2C143437%2C151195%2C144782%2C142474%2C141927%2C143988%2C144335%2C151375%2C151376%2C151377%2C141895%2C151378%2C141579%2C141562%2C151365%2C144387%2C151379%2C144104%2C151438%2C151443%2C151444%2C144623%2C141482%2C141924%2C143303%2C148129%2C145933%2C142442%2C144066%2C141780%2C144293%2C146608%2C144871%2C144021%2C144722%2C141667%2C144458%2C143692%2C145293%2C142278%2C143836%2C141362%2C141311%2C142508%2C141834&data%5B%5D=xml'
>>> get_river(sabine)
Sabine River At Deweyville (DWYT2) stage (24.12) is above [FLood Stage: 24.0]
>>> get_river(riogrande)
>>> get_river(redriver)
Red River At Lake Texoma near Denison (DSNT2) stage (619.29) is above [Major FLood Stage: 34.0]
Red River Above Red River Lock 2 (RRBL1) stage (64.42) is above [Major FLood Stage: 40.0]
>>> get_river(mississippi)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/skywalker/scripts/python/riverwarn/riverwarn.py", line 73, in get_river
if stage < action:
UnboundLocalError: local variable 'action' referenced before assignment
I've moved the variables around the appropriate if
and for
blocks but that doesn't seem to help. I've tried assigning them as global
variables as mentioned here. I've also gone back over the URL data from water.weather.gov and compared each river stage/flood alerts and it all appears to be the same for each river. So now I'm just confused as to why the variable 'action' is referenced before assignment in the Mississippi river data when it's not in the first three.
Upvotes: 1
Views: 1295
Reputation: 3358
Just from looking at the code, the reason might be:
ALERT_LEVELS
is empty, so for a in ALERT_LEVELS
doesn't run
or
none of the objects in ALERT_LEVELS
matches in data[n]['alerts']
, so if a in data[n]['alerts']
never triggered
A workaround to this is set action = None
before the for loop and check whether action is None
afterwards to handle this situation.
Cool App btw :)
Upvotes: 3