Clash Royale CLAN TAG#URR8PPP
How to init 'MySocket' object with standart socket object?
I want to write my own socket class for server-client talking with RSA and AES encryption, and for server side I need to overload accept() function to return not (socket, address) pair, but (MySocket, address). So that's why I need MySocket class to be initializable with another socket.
This is simplified version of my code:
import socket as sock
class MySocket(sock.socket):
def __init__(self, socket_obj = None):
if socket_obj == None:
sock.socket.__init__(self, family = sock.AF_INET, type = sock.SOCK_STREAM)
else:
assert(socket_obj.family == sock.AF_INET and socket_obj.type == sock.SOCK_STREAM)
self = socket_obj
self.key = 'value'
my_socket = MySocket() # works fine
print('First worked')
my_socket = MySocket(socket_obj = sock.socket()) # falls with error
print('Second also worked')
And after executing this code, I get an error:
Traceback (most recent call last):
File "./pyoverflow.py", line 19, in <module>
my_socket = MySocket(socket_obj = sock.socket()) # falls with error
File "./pyoverflow.py", line 13, in __init__
self.key = 'value'
AttributeError: 'socket' object has no attribute 'key'
As I understand, the problem is in the #9 string self = socket_obj
, but googling the error didn't give anything.
self = socket_obj
self
self
self.key = value
MySocket
self
1 Answer
1
If MySocket
is a subclass of socket
, then a MySocket
instance is a socket
instance; it can't become a different socket
instance, nor can you change another socket
instance into a MySocket
if it wasn't one already.1
MySocket
socket
MySocket
socket
socket
socket
MySocket
There are two possible things that do make sense here, however.
First, instead of being a socket
, your MySocket
can own a socket
, and provide the same interface as the socket
type by delegating calls to its owned socket
. Then, you can easily choose whether to own a newly-created socket, or one that was passed in. Something like this:
socket
MySocket
socket
socket
socket
class MySocket:
def __init__(self, socket_obj = None):
if socket_obj is None:
socket_obj = socket.socket(self, family = sock.AF_INET, type = sock.SOCK_STREAM)
self._socket_obj = socket_obj
self.key = 'value'
def accept(self):
addr, sock = self._socket_obj.accept()
return addr, MySocket(sock)
def __getattr__(self, name):
if name.startswith('_'):
raise AttributeError(name)
return getattr(self._socket_obj, name)
Writing explicit delegators (whether manually, or by looping over inspect.getmembers(socket.socket)
and creating them programmatically) is probably a better design here than __getattr__
, but this gets the idea across.
inspect.getmembers(socket.socket)
__getattr__
The other option is to to do effectively what ssl.SSLSocket
does.
ssl.SSLSocket
Socket objects are basically just a thin wrapper around a file descriptor. You can call detach
on a socket to steal its fd, and then you can pass that fd into the socket
constructor:
detach
socket
class MySocket(sock.socket):
def __init__(self, socket_obj=None):
if socket_obj is None:
super().__init__(family=sock.AF_INET, type=sock.SOCK_STREAM)
else:
super().__init__(fileno=socket_obj.detach())
self.key = 'value'
1. Actually, in Python, you can sometimes change the type of a live object, by setting its __class__
attribute. But this is almost always a bad idea, and wanting to do so is usually a sign that your design has gone very wrong somewhere.
__class__
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
This code doesn’t make any sense. Assigning a new value to
self
just rebinds the local variableself
to another object for the rest of this function. So now, you’re callingself.key = value
on that other object, which fails. But if it didn’t fail, you still wouldn’t have done anything to theMySocket
you’re supposed to be initializing, but instead to the other object you reboundself
to.– abarnert
36 mins ago