2017-07-14 3 views
0

Es ist höchste Zeit, dass ich Klassen benutze. Ich habe immer einen anderen Weg gefunden. Gestern habe ich genau den Code gefunden, den ich brauche, aber es ist in einer netten kleinen Klasse und ich kann nicht herausfinden, wie ich darauf zugreifen kann. Ich habe hier alle Tutorials und ähnliche Lösungen gelesen. Ich kann einfach nicht meinen Kopf darum wickeln. Der einzige Teil, den ich geschrieben habe, ist "main()", was der Teil ist, der nicht funktioniert. Ich habe ein paar Dutzend Wege neu geschrieben, und keiner von ihnen funktioniert so, wie ich es von ihnen erwarte.Python-Fehler "ungebundene Methode muss mit Instanz als erstes Argument aufgerufen werden"

Vielen Dank für Ihre Zeit und Geduld.

Alle Kredit geht an Nathan Adams - aka dinnerbone

import socket 
import struct 

class MinecraftQuery: 
    MAGIC_PREFIX = '\xFE\xFD' 
    PACKET_TYPE_CHALLENGE = 9 
    PACKET_TYPE_QUERY = 0 
    HUMAN_READABLE_NAMES = dict(
     game_id  = "Game Name", 
     gametype = "Game Type", 
     motd  = "Message of the Day", 
     hostname = "Server Address", 
     hostport = "Server Port", 
     map   = "Main World Name", 
     maxplayers = "Maximum Players", 
     numplayers = "Players Online", 
     players  = "List of Players", 
     plugins  = "List of Plugins", 
     raw_plugins = "Raw Plugin Info", 
     software = "Server Software", 
     version  = "Game Version", 
    ) 

    def __init__(self, host, port, timeout=10, id=0, retries=2): 
     self.addr = (host, port) 
     self.id = id 
     self.id_packed = struct.pack('>l', id) 
     self.challenge_packed = struct.pack('>l', 0) 
     self.retries = 0 
     self.max_retries = retries 

     self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
     self.socket.settimeout(timeout) 

    def send_raw(self, data): 
     self.socket.sendto(self.MAGIC_PREFIX + data, self.addr) 

    def send_packet(self, type, data=''): 
     self.send_raw(struct.pack('>B', type) + self.id_packed + self.challenge_packed + data) 

    def read_packet(self): 
     buff = self.socket.recvfrom(1460)[0] 
     type = struct.unpack('>B', buff[0])[0] 
     id = struct.unpack('>l', buff[1:5])[0] 
     return type, id, buff[5:] 

    def handshake(self, bypass_retries=False): 
     self.send_packet(self.PACKET_TYPE_CHALLENGE) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      if not bypass_retries: 
       self.retries += 1 

      if self.retries < self.max_retries: 
       self.handshake(bypass_retries=bypass_retries) 
       return 
      else: 
       raise 

     self.challenge = int(buff[:-1]) 
     self.challenge_packed = struct.pack('>l', self.challenge) 

    def get_status(self): 
     if not hasattr(self, 'challenge'): 
      self.handshake() 

     self.send_packet(self.PACKET_TYPE_QUERY) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      self.handshake() 
      return self.get_status() 

     data = {} 

     data['motd'], data['gametype'], data['map'], data['numplayers'], data['maxplayers'], buff = buff.split('\x00', 5) 
     data['hostport'] = struct.unpack('<h', buff[:2])[0] 
     buff = buff[2:] 
     data['hostname'] = buff[:-1] 

     for key in ('numplayers', 'maxplayers'): 
      try: 
       data[key] = int(data[key]) 
      except: 
       pass 

     return data 

    def get_rules(self): 
     if not hasattr(self, 'challenge'): 
      self.handshake() 

     self.send_packet(self.PACKET_TYPE_QUERY, self.id_packed) 

     try: 
      type, id, buff = self.read_packet() 
     except: 
      self.retries += 1 
      if self.retries < self.max_retries: 
       self.handshake(bypass_retries=True) 
       return self.get_rules() 
      else: 
       raise 

     data = {} 

     buff = buff[11:] # splitnum + 2 ints 
     items, players = buff.split('\x00\x00\x01player_\x00\x00') # Shamefully stole from https://github.com/barneygale/MCQuery 

     if items[:8] == 'hostname': 
      items = 'motd' + items[8:] 

     items = items.split('\x00') 
     data = dict(zip(items[::2], items[1::2])) 

     players = players[:-2] 

     if players: 
      data['players'] = players.split('\x00') 
     else: 
      data['players'] = [] 

     for key in ('numplayers', 'maxplayers', 'hostport'): 
      try: 
       data[key] = int(data[key]) 
      except: 
       pass 

     data['raw_plugins'] = data['plugins'] 
     data['software'], data['plugins'] = self.parse_plugins(data['raw_plugins']) 

     return data 

    def parse_plugins(self, raw): 
     parts = raw.split(':', 1) 
     server = parts[0].strip() 
     plugins = [] 

     if len(parts) == 2: 
      plugins = parts[1].split(';') 
      plugins = map(lambda s: s.strip(), plugins) 

     return server, plugins 

def main(): 
    check = MinecraftQuery.get_status('10.0.10.8',25565) 
    print check 

main() 
+0

Sie müssen die Klasse vor dem Aufruf einer Methode instanziieren. Erstellen Sie zuerst eine neue Instanz mit MinecraftQuery (Host, Port), wobei Host und Port offensichtlich die Host- und Port-Namen sind. Dann rufe den Status darauf an. –

Antwort

0

Ich denke, es sollte wie folgt sein. Probieren Sie, ob es funktioniert.

def main(): 
    check = MinecraftQuery('10.0.10.8', 25565) 
    # It calls the __init__() method and constructs an object/instance of the class named 'MinecraftQuery' 
    # using the given arguments and associate it with the given identifier 'check' 
    check.get_status() 
    # Now, this invokes the get_status() method of the instance named 'check'. 
    print check 
+1

Ja! Ich bekomme in main() keinen Fehler mehr. Jetzt habe ich Timeout-Fehler, die auf Pakete warten. Ich muss das für eine andere Version von Minecraft optimieren. Danke! –

0

Ein ungebundenes Methode ist eine, die nicht mit einer Instanz einer Klasse aufgerufen wird. Ihr Fehler bedeutet, dass Sie die Methode für die Klasse und nicht für eine Instanz aufrufen. Daher sollten Sie zuerst eine Instanz der Klasse erstellen und dann die Methode aufrufen.

Verwandte Themen