NameError表示未定义变量,仅在某些地方 [英] NameError says variable is not defined, but only in some places

查看:106
本文介绍了NameError表示未定义变量,仅在某些地方的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个保持活动状态,该功能每30秒发送一些数据以保持telnet连接的打开.

I am trying to implement a keep-alive that sends some data every 30 seconds to keep a telnet connection open.

我的代码每秒调用一次reinitScore.该函数有时会调用calculateWinner,后者会通过telnet通过stelnet.send(data)发送数据.

My code calls reinitScore every second. This function will sometimes call calculateWinner, which sends the data through telnet via stelnet.send(data).

问题是,当我在任何函数内调用stelnet.send(data)时,都会引发NameError: global name 'stelnet' is not defined.

The problem is, when I call stelnet.send(data) inside any function, it raises a NameError: global name 'stelnet' is not defined.

我的问题是:为什么stelnet.send(data)会在一个地方而不是另一个地方工作?

My questions is: why would stelnet.send(data) work in one place, and not another?

这是我的代码中有关telnet传输和函数调用的部分:

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)

我试图在很多地方将stelnet声明为global变量,但是它没有任何改变---我总是得到未定义"的NameError.

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.

推荐答案

响应您的更新代码...错误消息是 still 正确的,因为尽管您在模块级别,您定义得太迟了.它的定义是在calculateWinner函数中使用后 出现的.

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 the calculateWinner function.

将代码精简到一个非常荒谬的最小示例,您正在执行以下操作:

Stripping your code down to a ridiculously minimal example, you are doing something like this:

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执行之前.

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 defined stelnet 1) where calculateWinner can get at it, and 2) before calculateWinner is executed.

建议

依赖全局可变状态的函数很难遵循,更不用说正确编码了.要说出什么取决于哪个变量,什么在修改它们,或者何时确定,这并不容易.另外,提出一个 MCVE 比原本应该的麻烦得多,因为看起来独立的功能可能并非如此.

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.

将尽可能多的模块级代码填充到main函数中,然后从if __name__ == '__main__':主体中调用它(以及其他操作)(因为即使 实际上在模块级别).

Stuff as much of your module-level code as you can into a main function, and call it (and nothing else) from the body of if __name__ == '__main__': (since even that is actually at module level).

考虑这样的事情:

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

这些函数仍然通过它们传递的共享字典连接,但是只有显式传递给该字典的函数才能更改其内容.

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.

这篇关于NameError表示未定义变量,仅在某些地方的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆