移至主內容

簡單處理Python匯入外部py檔時常出現的(NameError: name '變數' is not defined)的問題

Submitted by 肥貓 on

前言

延續上一篇文章的討論,我接下來想做的是依照各國的ISO簡寫(iso_code),將個別國家的疫情資料存成一個dataframe。但是我當然不可能一個一個慢慢key,所以是利用組合字串的方式來處理。原本是想要寫迴圈直接做,但是我遇到不少問題暫時作罷,替代的方法先用迴圈是把字串組合成一堆例如(下面):

AFG=world[world['iso_code']== 'AFG']
ALB=world[world['iso_code']== 'ALB']
DZA=world[world['iso_code']== 'DZA']
AND=world[world['iso_code']== 'AND']
AGO=world[world['iso_code']== 'AGO']
AIA=world[world['iso_code']== 'AIA']
ATG=world[world['iso_code']== 'ATG']
ARG=world[world['iso_code']== 'ARG']

...

 

之後,把這些寫入一個外部的py檔案再餵給Python。具體的作法請參照我截圖中的第58-74行處(原程式碼則在下面),只是今天沒辦法逐行解釋這些是怎麼寫出來的。

import sys
sys.stdout = open('syntax1.py', "w")

...(與本題無關的指令稿逕行省略,下同)

levels = countries_list
for n in levels:
    #print(n)
    f"""{n}=world[world['iso_code']== {n}]"""
...
    print(f"""{n}=world[world['iso_code']== '{n}']""",file=sys.stdout)

簡單處理Python匯入外部py檔時常出現的(NameError: name '變數' is not defined)的問題

好不容易將字串組合成一組約230行的指令碼,存成py檔案準備匯入。在用R的時候很簡單,用source("(path and) filename")就可以搞定。但是使用import函數的時候則踢到鐵板,系統一直跳出NameError: name 'world' is not defined的錯誤訊息。原本以為是括號括錯地方,只是除錯後還是沒用。另一個跡象則是我把裡面的字串貼到console去,他就可以正常執行,但是我總不要用滑鼠鍵盤逐行慢慢貼,寫程式就是要一氣呵成啊。

爬文之後猜測原因(至少我的解讀)是這樣,import雖然可直譯「匯入」,實務上比較像呼叫一個應用程式在外面開啟。原本你是要自己手動開的,但是請系統幫你叫。所以要是你沒有在原本的指令稿內把環境變數設好的話,那你主檔案的變數當然就抓不到。可是設環境變數一方面繁瑣(我一時還真的不知道該怎麼辦),二來每次重跑檔案(指令已經半自動化了),就會把東西蓋過去。怎麼辦呢?

這時候就要改變思維,到另一種指令execute(「執行」)(在Python 3 是exec指令;Python 2則是execfile指令;這裡採用Python 3)去。我大概把他理解成,你是在這個地方執行另一個外來的script。至於為什麼不是叫作import(我覺得這真的比較像匯入啊),那已經不重要了,反正實務上似乎這樣理解,操作起來比較順。所以我爬文後就依樣畫葫蘆,把指令寫成:

exec(open('syntax1.py').read())

嘿!這樣就行了。至少我把整個Spyder重開後重跑,是有得到我想要的結果的。回顧了底下一堆被我#掉的地方才知道,原來exec的指令我有嘗試過,只是不知為何後來沒有沿用。原本兩分鐘就能解決的事,我又花了好幾個小時debug,還真是踏破鐵鞋無覓處啊!