NameError 说变量未定义,但仅在某些地方
NameError says variable is not defined, but only in some places
我正在尝试实现每 30 秒发送一些数据以保持 telnet 连接打开的保持活动状态。
我的代码每秒调用 reinitScore
。此函数有时会调用 calculateWinner
,它通过 stelnet.send(data)
.
通过 telnet 发送数据
问题是,当我在任何函数中调用 stelnet.send(data)
时,它会引发 NameError: global name 'stelnet' is not defined
.
我的问题是:为什么 stelnet.send(data)
在一个地方工作,而不在另一个地方工作?
这是我的代码中涉及 telnet 传输和函数调用的部分:
import socket, select, string, sys
import string
import threading
leftKeyCounter = 0
rightKeyCounter = 0
frontKeyCounter = 0
backKeyCounter = 0
# function called by reinitScore
def calculateWinner(d):
scores = {}
high_score = 0
for key, value in d.items():
try:
scores[value].append(key)
except KeyError:
scores[value] = [key]
if value > high_score:
high_score = value
results = scores[high_score]
if len(results) == 1:
print results[0]
stelnet.send(results[0])
return results[0]
else:
print 'TIE'
return 'TIE', results
#called once and repeat itselfs every second
def reinitScore():
threading.Timer(1, reinitScore).start()
#globaling for changing the content
global leftKeyCounter
global rightKeyCounter
global frontKeyCounter
global backKeyCounter
values = {'left' : leftKeyCounter, 'right' : rightKeyCounter, 'front' : frontKeyCounter, 'back' : backKeyCounter}
if (leftKeyCounter != 0 or rightKeyCounter != 0 or frontKeyCounter != 0 or backKeyCounter != 0):
calculateWinner(values)
leftKeyCounter = 0
rightKeyCounter = 0
frontKeyCounter = 0
backKeyCounter = 0
print "back to 0"
reinitScore()
if __name__ == "__main__":
if(len(sys.argv) < 3) :
print 'Usage : python telnet.py hostname port'
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
stelnet = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
stelnet.settimeout(2)
# connect to remote host
try :
stelnet.connect((host, port))
except :
print 'Unable to connect'
sys.exit()
print 'Connected to remote host'
while True:
// ... Some code that has nothing to do with telnet
while 1:
socket_list = [sys.stdin, stelnet]
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
for sock in read_sockets:
if sock == stelnet:
data = sock.recv(4096)
if not data :
print 'Connection closed'
sys.exit()
else :
sys.stdout.write(data)
else :
msg = sys.stdin.readline()
stelnet.send(msg)
我试图在很多地方将 stelnet
声明为 global
变量,但它没有改变任何东西 --- 我总是得到 "not defined" NameError
.
您的代码无法正常工作,因为您没有将 stelnet
传递给您的函数。
响应您更新的代码...错误消息仍然正确,因为尽管您在模块级别定义了stelnet
,但您已经定义了太晚了。它的定义发生在之后它在calculateWinner
函数中的使用。
将您的代码简化为一个可笑的最小示例,您正在做这样的事情:
def calculateWinner():
# A leap of faith... There is no `stelnet` defined
# in this function.
stelnet.send(results[0])
def reinitScore():
# Indirectly depends on `stelnet` too.
calculateWinner()
# But we haven't defined `stelnet` yet...
reinitScore() # Kaboom!
# These lines will never run, because the NameError has
# already happened.
if __name__ == '__main__':
stelnet = ... # Too late.
calculateWinner
依赖于函数编译时 不存在 的名称。它是否有效或崩溃取决于其他代码是否定义了 stelnet
1) calculateWinner
可以获取它的位置,以及 2) 在执行 calculateWinner
之前。
建议
依赖于全局可变状态的函数很难理解,更不用说正确编码了。很难分辨什么取决于哪些变量,或者什么在修改它们,或者什么时候。此外,想出一个 MCVE 比它应该的更麻烦,因为看起来独立的函数可能不是。
将尽可能多的模块级代码填充到 main
函数中,并从 if __name__ == '__main__':
函数体中调用它(仅此而已)(因为甚至 那个实际上是在模块级别)。
考虑这样的事情:
def reinit_score(output_socket, shared_scores):
# Ensuring safe concurrent access to the `shared_scores`
# dictionary is left as an exercise for the reader.
winner = ... # Determined from `shared_scores`.
output_socket.send(winner)
for key in shared_scores:
shared_scores[key] = 0
threading.Timer(
interval=1,
function=reinit_score,
args=[output_socket, shared_scores],
).start()
def main():
output_socket = ... # This was `stelnet`.
shared_scores = {...} # A dictionary with 4 keys: L/R/U/D.
reinit_score(output_socket, shared_scores)
while True:
play_game(shared_scores)
# `play_game` mutates the `shared_scores` dictionary...
if __name__ == '__main__':
main()
这些函数仍然通过它们传递的共享字典连接,但只有明确传递给该字典的函数才能更改其内容。
我正在尝试实现每 30 秒发送一些数据以保持 telnet 连接打开的保持活动状态。
我的代码每秒调用 reinitScore
。此函数有时会调用 calculateWinner
,它通过 stelnet.send(data)
.
问题是,当我在任何函数中调用 stelnet.send(data)
时,它会引发 NameError: global name 'stelnet' is not defined
.
我的问题是:为什么 stelnet.send(data)
在一个地方工作,而不在另一个地方工作?
这是我的代码中涉及 telnet 传输和函数调用的部分:
import socket, select, string, sys
import string
import threading
leftKeyCounter = 0
rightKeyCounter = 0
frontKeyCounter = 0
backKeyCounter = 0
# function called by reinitScore
def calculateWinner(d):
scores = {}
high_score = 0
for key, value in d.items():
try:
scores[value].append(key)
except KeyError:
scores[value] = [key]
if value > high_score:
high_score = value
results = scores[high_score]
if len(results) == 1:
print results[0]
stelnet.send(results[0])
return results[0]
else:
print 'TIE'
return 'TIE', results
#called once and repeat itselfs every second
def reinitScore():
threading.Timer(1, reinitScore).start()
#globaling for changing the content
global leftKeyCounter
global rightKeyCounter
global frontKeyCounter
global backKeyCounter
values = {'left' : leftKeyCounter, 'right' : rightKeyCounter, 'front' : frontKeyCounter, 'back' : backKeyCounter}
if (leftKeyCounter != 0 or rightKeyCounter != 0 or frontKeyCounter != 0 or backKeyCounter != 0):
calculateWinner(values)
leftKeyCounter = 0
rightKeyCounter = 0
frontKeyCounter = 0
backKeyCounter = 0
print "back to 0"
reinitScore()
if __name__ == "__main__":
if(len(sys.argv) < 3) :
print 'Usage : python telnet.py hostname port'
sys.exit()
host = sys.argv[1]
port = int(sys.argv[2])
stelnet = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
stelnet.settimeout(2)
# connect to remote host
try :
stelnet.connect((host, port))
except :
print 'Unable to connect'
sys.exit()
print 'Connected to remote host'
while True:
// ... Some code that has nothing to do with telnet
while 1:
socket_list = [sys.stdin, stelnet]
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
for sock in read_sockets:
if sock == stelnet:
data = sock.recv(4096)
if not data :
print 'Connection closed'
sys.exit()
else :
sys.stdout.write(data)
else :
msg = sys.stdin.readline()
stelnet.send(msg)
我试图在很多地方将 stelnet
声明为 global
变量,但它没有改变任何东西 --- 我总是得到 "not defined" NameError
.
您的代码无法正常工作,因为您没有将 stelnet
传递给您的函数。
响应您更新的代码...错误消息仍然正确,因为尽管您在模块级别定义了stelnet
,但您已经定义了太晚了。它的定义发生在之后它在calculateWinner
函数中的使用。
将您的代码简化为一个可笑的最小示例,您正在做这样的事情:
def calculateWinner():
# A leap of faith... There is no `stelnet` defined
# in this function.
stelnet.send(results[0])
def reinitScore():
# Indirectly depends on `stelnet` too.
calculateWinner()
# But we haven't defined `stelnet` yet...
reinitScore() # Kaboom!
# These lines will never run, because the NameError has
# already happened.
if __name__ == '__main__':
stelnet = ... # Too late.
calculateWinner
依赖于函数编译时 不存在 的名称。它是否有效或崩溃取决于其他代码是否定义了 stelnet
1) calculateWinner
可以获取它的位置,以及 2) 在执行 calculateWinner
之前。
建议
依赖于全局可变状态的函数很难理解,更不用说正确编码了。很难分辨什么取决于哪些变量,或者什么在修改它们,或者什么时候。此外,想出一个 MCVE 比它应该的更麻烦,因为看起来独立的函数可能不是。
将尽可能多的模块级代码填充到 main
函数中,并从 if __name__ == '__main__':
函数体中调用它(仅此而已)(因为甚至 那个实际上是在模块级别)。
考虑这样的事情:
def reinit_score(output_socket, shared_scores):
# Ensuring safe concurrent access to the `shared_scores`
# dictionary is left as an exercise for the reader.
winner = ... # Determined from `shared_scores`.
output_socket.send(winner)
for key in shared_scores:
shared_scores[key] = 0
threading.Timer(
interval=1,
function=reinit_score,
args=[output_socket, shared_scores],
).start()
def main():
output_socket = ... # This was `stelnet`.
shared_scores = {...} # A dictionary with 4 keys: L/R/U/D.
reinit_score(output_socket, shared_scores)
while True:
play_game(shared_scores)
# `play_game` mutates the `shared_scores` dictionary...
if __name__ == '__main__':
main()
这些函数仍然通过它们传递的共享字典连接,但只有明确传递给该字典的函数才能更改其内容。