Python奇怪的代码错误

时间:2013-01-06 07:00:55

标签: python

我有一个IRC机器人,我正在尝试获取游戏服务器(GTA SA多人游戏)的信息。 我有现成的查询,但我无法将其实现到我的机器人中。如果我尝试加载相同的脚本,但没有进入bot的结构,它可以工作。它给我的错误是

  

NameError:名称'ip'未定义

我尝试在def(inp,say=None)中添加ip地址作为参数,但它仍然无效。这就是代码:

from util import Query
from util import hook
import sys

@hook.command
def serverinfo(inp,ip="",port="",say=None):
    ip = "78.129.221.58"
    port = 7777 
if len(sys.argv) >= 3:
    ip = str(sys.argv[1])
    port = int(sys.argv[2])

query = Query(ip,port)
info = query.GetInformation()
say(info)
if info['players'] <= 100:
    say(query.GetPlayers())
    say(query.GetDetailedPlayers())
else: say('can\' get players because players is above 100')
say(query.Ping())
query.Close()

我导入的查询

import socket, struct, random, datetime
from cStringIO import StringIO

class Query:
    def __init__(self, ip, port):
        self.ip, self.port = socket.gethostbyname(ip), port
        self.data = StringIO("")
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.connect((ip, port))
        self.sock.settimeout(1)

    def CreatePacket(self, opcode):
        ips = self.ip.split('.');
        packet = "SAMP{0}{1}{2}{3}{4}{5}{6}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode)
        if opcode == 'p':
            packet += struct.pack("BBBB", random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
        return packet

    def GetInformation(self):
        try:
            self.sock.send(self.CreatePacket('i'))
            info = {}
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            info['passworded'] = struct.unpack('?', self.data.read(1))[0]
            info['players'] = struct.unpack('h', self.data.read(2))[0]
            info['maxplayers'] = struct.unpack('h', self.data.read(2))[0]

            info['hostname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
            info['gamemode'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
            info['mapname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
        except socket.timeout:
            info['error'] = 1
        return info

    def GetRules(self):
        try:
            self.sock.send(self.CreatePacket('r'))
            rules = {}
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            rulecount = struct.unpack('h', self.data.read(2))[0]
            for i in range(rulecount):
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                rules[name] = self.data.read(struct.unpack('b', self.data.read(1))[0])
        except socket.timeout:
            rules['error'] = 1
        return rules

    def GetPlayers(self):
        try:
            self.sock.send(self.CreatePacket('c'))
            players = []
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            playercount = struct.unpack('h', self.data.read(2))[0]
            for i in range(playercount):
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                players.append([name, struct.unpack('i', self.data.read(4))[0]])
        except socket.timeout:
            players = {'error': 1}
        return players

    def GetDetailedPlayers(self):
        try:
            self.sock.send(self.CreatePacket('d'))
            players = []
            self.data = StringIO(self.sock.recv(2048))
            self.data.read(11)
            playercount = struct.unpack('h', self.data.read(2))[0]
            for i in range(playercount):
                playerid = struct.unpack('b', self.data.read(1))[0]
                name = self.data.read(struct.unpack('b', self.data.read(1))[0])
                score = struct.unpack('i', self.data.read(4))[0]
                ping = struct.unpack('i', self.data.read(4))[0]
                players.append([playerid, name, score, ping])
        except socket.timeout:
            players = {'error': 1}
        return players

    def Close(self):
        self.sock.close()   

    def Ping(self):
        packet = self.CreatePacket('p')
        a = datetime.datetime.now()
        self.sock.send(packet)
        self.sock.recv(2048)
        b = datetime.datetime.now()
        c = b - a
        return int((c.days * 24 * 60 * 60 + c.seconds) * 1000 + c.microseconds / 1000.0)

class Rcon:
    def __init__(self, ip, port, password):
        self.ip, self.port, self.password = socket.gethostbyname(ip), port, password
        self.data = StringIO("")
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.connect((ip, port))
        self.sock.settimeout(0.5)

    def CreatePacket(self, opcode, password, command):
        ips = self.ip.split('.');
        packet = "SAMP{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode, chr(len(password) & 0xFF), chr(len(password) >> 8 & 0xFF), password, chr(len(command) & 0xFF), chr(len(command) >> 8 & 0xFF), command)
        return packet

    def Send(self, command):
        self.sock.send(self.CreatePacket('x', self.password, command))
        output = []
        while 1:
            try:
                self.data = StringIO(self.sock.recv(2048))
                self.data.read(11)
                strlen = struct.unpack('h', self.data.read(2))[0]
                if strlen == 0: break
                output += [self.data.read(strlen)]
            except: break;
        return output

    def Close(self):
        self.sock.close()

有什么想法吗?

编辑:在我做了一些更改后,给了我以下错误:

query = Query(ip,port)
     

TypeError:'module'对象不可调用

我基本上改变了ip和port的位置,将其移出serverinfo命令。

    from util import Query
from util import hook

ip = "78.129.221.58"
port = 7777
query = Query(ip,port)
info = query.GetInformation()

@hook.command
def serverinfo(inp,ip="",port="",say=None):
    say(info)
if info['players'] <= 100:
    say(query.GetPlayers())
    say(query.GetDetailedPlayers())
else: say('can\' get players because players are above 100')
say(query.Ping())
query.Close()

2 个答案:

答案 0 :(得分:0)

问题在于这一行:

query = Query(ip,port)

如果使用命令行参数初始化失败或传入的参数不足,则ip将不会被初始化,从而导致上述错误。

此外,测试脚本的更好方法是这样的:

def main():
    if len(sys.argv) >= 3:
        ip = str(sys.argv[1])
        port = int(sys.argv[2])
        query = Query(ip,port)
        # start using query
    else:
        raise Exception("Insufficient args passed in")
if __name__ == '__main__':
    main()

引发异常/错误或打印出某些内容可以保证您知道传入的args不足。另外,也许可以将所有代码移开到某个函数中?

答案 1 :(得分:0)

尝试将其添加到python代码的开头:

ip = "78.129.221.58"
port = 7777

尝试

query = Query.Query(ip, port)