iT邦幫忙

0

python exceptions.UnboundLocalError(已解決)

饅頭 2017-04-28 18:05:4425988 瀏覽

我在程式碼一開始有設定很多變數
在跑的時候都沒有問題
但是在最近增加Result這個list的時候

出現
print Result exceptions.UnboundLocalError: local variable 'Result' referenced before assignment

Result = []
ResultList = [
	'Unsuceessfully in Linux!','Suceessfully in Linux!'
	'Unsuceessfully in Windows7!','Suceessfully in Windows7!'
	]

def cbBody(body):
	if body == "Windows" :
		return main_linux(reactor, url=u"".encode("utf-8"))
	
	elif body == "Server : Host wil work":
		sleep(60)
		return main_wait(reactor, url=u"".encode("utf-8"))
	
	elif (body in ResultList) == True : 
        print Result         ##這裡出問題
        Result.append(body)
		if len(Result) == 1 :
			return main_wait(reactor, url=u"".encode("utf-8"))
		else :
			if ('Unsuceessfully in Linux!' in Result) == True :
				sys.exit(-1)
			elif ('Unsuceessfully in Windows7!' in Result) == True:
				sys.exit(-1)
			print Result
			Result = []
	else:
		return main_wait(reactor, url=u"".encode("utf-8"))

def cbRequest(response):
	print 'Response headers:'
	print pformat(list(response.headers.getAllRawHeaders()))
	d = readBody(response)
	d.addCallback(cbBody)
	return d

react(main, argv[1:], reactor)

同樣的Result 在 cbRequest 裡面可以使用(print得出來)
但是在cbBody 裡出現
exceptions.UnboundLocalError: local variable 'Result' referenced before assignment

在同一個 cbBody 裡面 使用 ResultList 沒問題
但是 Result 卻出現錯誤訊息

我有上網查可以加 global
但是因為我要將結果加到 Result
如果設定 global Result
在跑第二次的時候 Result就會回到預設 Result = []
(我預期結果要執行到else)
有哪位大大知道其他解決方法
或是知道問題出在哪裡嗎?/images/emoticon/emoticon02.gif

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

4
bizpro
iT邦大師 1 級 ‧ 2017-04-29 13:56:35
最佳解答

基本觀念:

  1. Python傳值不傳址, 看得到吃不到.
  2. Python是函數(function)式語言, 函數的意義如同變數, 在函數中的變數範圍僅及於函數的範圍.
  3. Python並無變數宣告(declaration)的機制, 必須透過等號對變數賦值(assignment)在記憶體中定址.

您的程式中, 您在函數外賦值了Result, ResultList變數, 由於是在函數外, 這兩個變數的"值傳進了"函數", 函數看到"了, 所以您可以print Result, 但函數不知道外部變數Result在記憶體中的位址, 如果函數要參照(reference)外部函數在記憶體中的位址, 就要用global來定址.

您說問題是出在print Result:

    print Result         ##這裡出問題
    Result.append(body)

其實是Result.append(body)的問題.

這就是"吃不到"的問題了. 所謂的吃, 指的是到記憶體位置處去改變記憶體中的值, 前面說過因為Python傳值不傳址, 而您又未用global來定址, 對Python來說, 您是不能改變這個外變數Result的值的, 因此當Python看到指令Result.append(body), 它把這裡的Result當成一個新的函數內變數, 變數名就是Result, 意思是, 函數外變數Result和函數內變數Result是不同的兩個變數, 而Python找不到您對這個函數內變數Result賦值(assignment), 所以就出現錯誤了:
local variable 'Result' referenced before assignment
錯誤中明明白白的告訴您這個Result是一個區域變數, 而您想要參照它(referenced 即定址, 吃), 但您卻未曾對這個區域變數Result賦值(assignment)過, 當然就不存在於記憶體中, 錯誤就這樣發生了.

這也說明了您對Result和ResultList的疑問.

看更多先前的回應...收起先前的回應...

/images/emoticon/emoticon34.gif

饅頭 iT邦新手 4 級 ‧ 2017-05-02 09:18:26 檢舉

感謝您的回答!!!
但是我在其他的function裡去測試Result.append
他可以抓到Result...

bizpro iT邦大師 1 級 ‧ 2017-05-02 13:53:59 檢舉

請問原始碼?

饅頭 iT邦新手 4 級 ‧ 2017-05-03 10:28:48 檢舉

我改了變數名稱之後就可以用了@@
原本Result 改成 GetResult

from twisted.internet import reactor
from sys import argv
from pprint import pformat
from twisted.internet.task import react
from twisted.web.client import Agent, readBody, FileBodyProducer
from twisted.web.http_headers import Headers
from StringIO import StringIO
from twisted.web.resource import Resource
from time import sleep


GetResult = []
Windows = "Bitbucket to Windows".encode("utf-8")
Linux = "Bitbucket to Linux".encode("utf-8")
Wait = "Have Result?".encode("utf-8")
ResultList = [
	'Unsuceessfully in CentOS6.5!','Suceessfully in CentOS6.5!',
	'Unsuceessfully in Windows7!','Suceessfully in Windows7!'
	]

def main(reactor, url=b""):
	message = FileBodyProducer(StringIO(Linux))
	agent = Agent(reactor)
	d = agent.request(
		'GET', url,
		Headers({'Content-Type': ['text/html; charset=UTF-8']}),
		message)
	d.addCallback(cbRequest)
	return d

def main_linux(reactor, url=b""):
	message = FileBodyProducer(StringIO(Windows))
	agent = Agent(reactor)
	d = agent.request(
		'GET', url,
		Headers({'Content-Type': ['text/html; charset=UTF-8']}),
		message)
	d.addCallback(cbRequest)
	return d

def main_wait(reactor, url=b""):
	message = FileBodyProducer(StringIO(Wait))
	agent = Agent(reactor)
	d = agent.request(
		'GET', url,
		Headers({'Content-Type': ['text/html; charset=UTF-8']}),
		message)
	d.addCallback(cbRequest)
	return d

def cbBody(body):
	get_massage = body
	print 'GetResult:',GetResult
	print get_massage
	if get_massage == "Windows" :
		return main_linux(reactor, url=u"".encode("utf-8"))
	
	elif get_massage == "Server : Host wil work":
		sleep(60)
		return main_wait(reactor, url=u"".encode("utf-8"))
	
	elif (get_massage in ResultList) == True :
		GetResult.append(get_massage)
		print 'GetResult in elif:',GetResult
		print len(GetResult)
		if len(GetResult) == 1 :
			return main_wait(reactor, url=u"".encode("utf-8"))
		else :
			if ('Unsuceessfully in Linux!' in GetResult) == True :
				sys.exit(-1)
			elif ('Unsuceessfully in Windows7!' in GetResult) == True:
				sys.exit(-1)
			print 'Result:',GetResult

	else:
		return main_wait(reactor, url=u"".encode("utf-8"))

def cbRequest(response):
	print 'Response headers:'
	print pformat(list(response.headers.getAllRawHeaders()))
	d = readBody(response)
	d.addCallback(cbBody)
	return d


react(main, argv[1:], reactor)

我要發表回答

立即登入回答