2017-06-10 39 views
0

我知道這之前已經問過,因爲我已經搜索周圍的答案,但我讀過的問題並沒有真正解決我的問題。我用Python3寫了一個河流警告系統。最初,腳本只能檢索距離我家最近的河流的數據,所以我決定做一個重寫或版本升級,我想,可以使用任何河流。一切都已經工作相當不錯,直到我進入密西西比河URL,然後我開始本地變量參考之前作業..有時

UnboundLocalError: local variable 'action' referenced before assignment.

這裏是代碼:

編輯 - 增加了全功能顯示,其中ALERT_LEVELS定義

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 

所以後來當我執行的功能get_river()這裏的結果:

>>> 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 

我已經將變量移到了相應的iffor塊的周圍,但這似乎沒有幫助。我試着將它們分配爲global變量,如here所述。我還回顧了water.weather.gov的URL數據,並比較了每個河流階段/洪水警報,並且它們對於每條河流看起來都是相同的。所以現在我只是混淆了爲什麼變量'action'在密西西比河數據中的前之前被引用爲,而不是前三個。

+0

ALERT_LEVELS如何定義?看起來你的代碼可能會達到以下條件:'如果stage alonkol

+0

用完整的代碼更新了OP,以顯示在哪裏定義了'ALERT_LEVELS'。對不起,我忘了它已被定義在HTML解析部分 –

回答

3

剛剛從看代碼,其原因可能是:

ALERT_LEVELS是空的,所以for a in ALERT_LEVELSdata[n]['alerts']運行

沒有任何物體在ALERT_LEVELS比賽,所以if a in data[n]['alerts']永不觸發

解決方法:在for循環前設置action = None並檢查是否action is None事後處理這種情況。

酷應用btw :)

+0

早些時候謝謝!它實際上是爲了瞭解我家附近的河是否足夠釣魚。然後我想我可以用它來檢查洪水階段併發出警報。 'ALERT_LEVELS'在腳本的html解析部分的前面定義過。我忘記了這一點,所以我編輯了OP,以顯示它在哪裏以及如何定義。 –

+0

我按照你的建議添加了'action = None',現在它在進行階段比較時拋出錯誤:'TypeError:unorderable types:float()

+0

當action爲None時,你可以添加另一個if語句來處理情況,比如'if action is None:do sth; elif stage Ding