I am trying to implement a keep-alive that sends some data every 30 seconds to keep a telnet connection open.
My code calls reinitScore
every second. This function will sometimes call calculateWinner
, which sends the data through telnet via stelnet.send(data)
.
The problem is, when I call stelnet.send(data)
inside any function, it raises a NameError: global name 'stelnet' is not defined
.
My questions is: why would stelnet.send(data)
work in one place, and not another?
Here is the part of my code that concerns telnet transfer and function calling:
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)
I tried to declare stelnet
as a global
variable at many places, but it doesn't change anything --- I always get the "not defined" NameError
.
Your code is not working because you are not passing
stelnet
to your function.In response to your updated code... The error message is still correct, because although you have defined
stelnet
at the module level, you've defined it too late. It's definition occurs after its use in thecalculateWinner
function.Stripping your code down to a ridiculously minimal example, you are doing something like this:
calculateWinner
depends on a name that does not exist when the function is compiled. Whether it works or crashes will depend on whether some other code has definedstelnet
1) wherecalculateWinner
can get at it, and 2) beforecalculateWinner
is executed.Suggestions
Functions that depend on global mutable state are hard to follow, let alone code correctly. It's not easy to tell what depends on which variables, or what's modifying them, or when. Also, coming up with an MCVE is more trouble than it should be, because functions that appear independent might not be.
Stuff as much of your module-level code as you can into a
main
function, and call it (and nothing else) from the body ofif __name__ == '__main__':
(since even that is actually at module level).Consider something like this:
These functions are still connected by the shared dictionary that they pass around, but only functions that are explicitly passed that dictionary can change its contents.