python - Pickling 对象实例给出 TypeError : __new__() missing required positional arguments

标签 python sockets pickle subclassing

我正在用 python 创建一个棋盘游戏,它要求我发送由自定义 Hex() 类创建的对象,该类是元组的子类。我面临的问题是,当服务器收到 pickled 消息(包含字符串和 Hex 对象的元组)时,它会抛出以下错误:

类型错误:__new__() 缺少 2 个必需的位置参数:“r”和“s”

我对 OOP 比较陌生,但我相信服务器在解包元组消息时正在尝试创建 Hex 对象,但它显然没有重新创建原始对象所需的信息,因为它已全部打包在对象本身中。

如果有人可以建议一种方法,我可以成功地将我的十六进制对象从客户端发送到服务器并返回,我将不胜感激。

代码如下:

server.py

import socket
import pickle

HOST = '127.0.0.1'
PORT = 57343
SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SOCK.bind((HOST, PORT))
SOCK.listen()

print('Server active, waiting for connections...')


conn, addr = SOCK.accept()
print('Connected to:', addr)
conn.send(pickle.dumps('conn test'))
print('test message sent to', conn)

while True:
    try:
        print('waiting for data')
        data = pickle.loads(conn.recv(2048))
        command, info = data
        if command == 'move':
            print('Received message', data)
        elif command == 'get':
            pass
        conn.sendall(pickle.dumps('game'))
    except (EOFError, ConnectionResetError) as err:
        print(err)
        break
print('Lost connection')
conn.close()
client.py

import tmp_hex_lib as hl
from network import Network

def main():
    game_over = False
    moves = []
    attack_switch = False
    net = Network()
    net.get_player()
    while not game_over:  # main game loop
        try:
            net.send(('get', None))
        except:
            game_over = True
            print("Couldn't find game")
            break

        selected_hex = hl.Hex(-13, 10, 3)
        print('selected_hex has type:', type(selected_hex))

        moves.append(selected_hex)
        if attack_switch:
            net.send(('attack', None))
        else:
            net.send(('move', 'this message works'))
            net.send(('move', selected_hex))  # if any other type is sent, game runs fine
        attack_switch = False

if __name__ == '__main__':
    main()
network.py

import socket
import pickle

class Network:
    def __init__(self):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server = "127.0.0.1"
        self.port = 57343
        self.addr = (self.server, self.port)
        self.player = self.connect()

    def get_player(self):
        return self.player

    def connect(self):
        try:
            self.client.connect(self.addr)
            print('connecting to server')
            data = pickle.loads(self.client.recv(2048))
            print('Received data:', data)
            return data
        except EOFError as err:
            print(err)

    def send(self, data):
        try:
            self.client.send(pickle.dumps(data))
            return pickle.loads(self.client.recv(2048))
        except socket.error as err:
            print(err)
tmp_hex_lib.py

class Hex(tuple):
    def __new__(self, q, r, s):
        return tuple.__new__(self, (q, r, s))

    def __init__(self, q, r, s):
        self.q = q
        self.r = r
        self.s = s
        assert not (round(q + r + s) != 0), "q + r + s must be 0"

最佳答案

所以在查阅pickle文档后,我发现了一段关于pickle类实例的文章。看来如果你定义自己的 __new__()方法,您还必须定义一个方法 __getnewargs__(self)返回 __new__() 所需的所有变量作为一个元组。例如(没有双关语)我的情况是:

tmp_hex_lib.py

class Hex(tuple):
    def __new__(self, q, r, s):
        return tuple.__new__(self, (q, r, s))

    def __getnewargs__(self):
        return self.q self.r, self.s

    def __init__(self, q, r, s):
        self.q = q
        self.r = r
        self.s = s
        assert not (round(q + r + s) != 0), "q + r + s must be 0"

希望这对其他人有帮助!

关于python - Pickling 对象实例给出 TypeError : __new__() missing required positional arguments,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56518913/

相关文章:

python - 查找列表中段落的第一个单词

java - 使用套接字在 java 同步方法中抛出 NullPointerException

python - _pickle.UnpicklingError : could not find MARK

python - 多处理时避免在每个子进程中加载​​ spaCy 数据

python - 在 python 中使用 dill 取消选择对象

python - Django 中 `annotate` + `values` + `union` 的错误结果

python - 如何通过多个条件选择某些列?

c - 提取文件内容并附加到套接字并发送套接字编程

node.js - 无法读取未定义的 'emit' 的属性 "Socket + Angular + Node "

python - 将 float 转换为位置格式的字符串(没有科学记数法和错误精度)