import json
import socket
class node:
def __init__(self,name,hostname,port,connected = False) -> None:
self.nodeName = name
self.hostname = hostname
self.port = port
self.connectStatus = connected
# self.outgoingSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
class NodeEncoder(json.JSONEncoder):
def default(self, o):
return o.__dict__
I am using this code to serialize this object. However, I want to also attach a socket to each object and still be able to print it.
However, when uncommenting the line with the outgoing socket I get this
AttributeError: 'socket' object has no attribute '__dict__'. Did you mean: '__dir__'?
I understand this is because a socket cannot be turned into a dictionary. Is there any way I can make it so everything stays the same but the socket just prints or whatever the default is?
Related
I am beginner in programming and trying to develop simple console messenger on Python. I have an idea to extend standard socket.socket object and add to it additional attribute "account_name". I created new class "NamedSoket" based on standard socket class. Here is my code:
class NamedSocket(socket):
def __init__(self, family=-1, type=-1, proto=-1, fileno=None, name=None):
super().__init__(family=-1, type=-1, proto=-1, fileno=None)
self.name = name
def accept(self):
fd, addr = self._accept()
sock = NamedSocket(self.family, self.type, self.proto, fileno=fd, name=self.name)
if getdefaulttimeout() is None and self.gettimeout():
sock.setblocking(True)
return sock, addr
server = NamedSocket()
server.bind(('', 8000))
server.listen()
client = NamedSocket('Bob')
client.connect(('localhost', 8000))
new_client, address = server.accept()
Although new socket objects are created successfully, they do not work properly.. Methods 'recv' and 'send' do not work.. Could you please explain to me, where is the problem?
P.S.: I understand, that my 'idea', maybe, is not good 'at all', but now I became very interested in 'inheritance issue'. From first look, it should work, but it does not...
I've replicated described actions as accurate as possible. This code is working without any error.
import socket as sk
class NamedSocket(sk.socket):
def __init__(self, family=sk.AF_INET, type=sk.SOCK_STREAM, proto=0, fileno=None, name=None):
super().__init__(family, type, proto, fileno)
self.name = name
def accept(self):
fd, addr = self._accept()
sock = NamedSocket(self.family, self.type, self.proto, fileno=fd, name=self.name)
if sk.getdefaulttimeout() is None and self.gettimeout():
sock.setblocking(True)
return sock, addr
server = NamedSocket()
server.bind(('', 8000))
server.listen()
client = NamedSocket(name='Bob')
client.connect(('localhost', 8000))
new_client, address = server.accept()
client.send('hello'.encode())
new_client.recv(1024)
I replaced default parameters in __init()__ method of NamedSocket class to AF_INET, SOCK_STREAM and 0 for the first three arguments. Running such script does not imply any error. You could try do the same changes or edit something related to IP address binded to socket being established on the server side, according to error message.
As you may see, your constructor method takes a bunch of optional parameters:
def __init__(self, family=-1, type=-1, proto=-1, fileno=None, name=None):
super().__init__(family=-1, type=-1, proto=-1, fileno=None)
self.name = name
When you try to create an object of class NamedSocket for client, you pass the only 'Bob' parameter, which, by precedence of function argument, will be passed to family argument, but not to name. For doing things in the key you want, you may write:
client = NamedSocket(name='Bob')
I'm trying to write a simple TCP socket server.
I'm getting this error:
File "patch", line 9, in __init__
self.__SocketServer__.listen(1)
AttributeError: 'NoneType' object has no attribute 'listen'
And I can't understand why.
Code:
class DataManager:
def __init__(self):
self.__port__ = 2121
self.__ip__ = "127.0.0.1"
self.__SocketServer__ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__SocketServer__ = self.__SocketServer__.bind((self.__ip__, self.__port__))
self.__SocketServer__.listen(1)
self.__log__("Waiting car connection...")
self.__CarSocket__, addr = self.__SocketServer__.accept()
self.__log__("Car socket connected")
self.__CarSocket__ = None
socket.bind() returns None. Don't assign this back to your socket attribute:
self.__SocketServer__ = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__SocketServer__.bind((self.__ip__, self.__port__))
self.__SocketServer__.listen(1)
On a side note: don't use __doubleunderscore__ names for your own projects. Python reserves this class of names for its own use.
If you want to mark names as internal to the instance, use single underscores at the start of names. Python classes have no privacy model, all attributes are always accessible from the outside.
So this suffices:
class DataManager:
def __init__(self):
self._port = 2121
self._ip = "127.0.0.1"
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.bind((self._ip, self._port))
self._socket.listen(1)
self._log("Waiting car connection...")
self._connection, addr = self._socket.accept()
self._log("Car socket connected")
self._connection = None
I've used more commonly-used names for the socket and connection, also adhering to the Python style guide.
Here is my code:
import socket
import select
class My_socket(socket.socket):
def __init__(self, soc = None):
if soc == None:
socket.socket.__init__(self, socket.AF_INET, socket.SOCK_STREAM)
....
else:
# how to use soc to initialize or replace parent part
....
rs, ws, es = select.select([my_socket_instance],[],[])
....
I want to create a my_socket class which has more functions, and when u pass no argument to its constructor, it will initialize its parent part automatically, but when u pass a socket instance as argument, it uses it as its parent so that my_socket can still work fine like just a socket ( for instance as an input of select function)
More specifically I met this problem when I get the (conn, addr) as a return of socket.accept(), and conn is socket type, I want to turn it to my_socket type, how to achieve that
thanks
First of all I need to say I've never tried coding in python before...
I'm trying to make a Twitch IRC bot working but I keep failing...
My bot.py code looks like this:
from src.lib import irc as irc_
from src.lib import functions_general
from src.lib import functions_commands as commands
from src.config import config
class PartyMachine:
def __init__(self, config):
self.config = config
self.irc = irc_.irc(config)
self.socket = self.irc.get_irc_socket_object()
def sock(self):
irc = self.irc
sock = self.socket
config = self.config
kage = sock
while True:
data = sock.recv(2048).rstrip()
if len(data) == 0:
pp('Connection was lost, reconnecting.')
sock = self.irc.get_irc_socket_object()
if config['debug']:
print (data)
my config.py is here:
'socket_buffer_size': 1024
My irc.py is here:
def get_irc_socket_object(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
self.sock = sock
try:
sock.connect((self.config['server'], self.config['port']))
except:
pp('Cannot connect to server (%s:%s).' % (self.config['server'], self.config['port']), 'error')
sys.exit()
sock.settimeout(None)
def sock_send(sock, send, self):
sock.send('USER %s\r\n' % self.config['username'], sock.encode('utf-8'), send.encode('utf-8'))
sock.send('PASS %s\r\n' % self.config['oauth_password'])
sock.send('NICK %s\r\n' % self.config['username'])
if self.check_login_status(sock.recv(1024)):
pp('Login successful.')
else:
pp('Login unsuccessful. (hint: make sure your oauth token is set in self.config/self.config.py).', 'error')
sys.exit()
and my serve.py is here:
from sys import argv
from src.bot import *
from src.config.config import *
bot = PartyMachine(config).sock()
It keeps failing with "AttributeError 'nonetype' object has no attribute 'recv'". How can this be ?
Your get_irc_socket_object(self) might be the problem. You call it with the line self.socket = self.irc.get_irc_socket_object(). This means that python expects the function get_irc_socket_object(self) to return a socket object, but you don't return anything (you just write self.sock = sock, which doesn't do anything because you use self.socket for the rest of your code). As a result, the function returns none, so now self.socket just has that as its value. Therefore, when you make the call to recv you get your error
Also, please clean up your variable names. Sock is used way too often in your code and makes it very hard to follow.
For convenience, I wanted to subclass socket to create an ICMP socket:
class ICMPSocket(socket.socket):
def __init__(self):
socket.socket.__init__(
self,
socket.AF_INET,
socket.SOCK_RAW,
socket.getprotobyname("icmp"))
def sendto(self, data, host):
socket.socket.sendto(self, data, (host, 1))
However, I can't override socket.sendto:
>>> s = icmp.ICMPSocket()
>>> s.sendto
<built-in method sendto of _socket.socket object at 0x100587f00>
This is because sendto is a "built-in method". According to the data model reference, this is "really a different disguise of a built-in function, this time containing an object passed to the C function as an implicit extra argument."
My question: is there anyway to override built-in methods when subclassing?
[Edit] Second question: if not, why not?
I know this doesn't answer your question, but you could put the socket into an instance variable. This is what Nobody also suggested in the comments.
class ICMPSocket():
def __init__(self):
self.s = socket.socket(
socket.AF_INET,
socket.SOCK_RAW,
socket.getprotobyname("icmp"))
def sendto(self, data, host):
self.s.sendto(data, (host, 1))
def __getattr__(self, attr):
return getattr(self.s, attr)
Re-edit : My first solution wasn't working, and after straggling with this for sometime , i can conclude that in the case of python socket when you can say that aggregation is much better than inheriting but in case you want to know how you can do
it using inheritance check this code:
import socket
class ICMPSocket(socket.socket):
def __init__(self):
self._sock = socket.socket(
socket.AF_INET,
socket.SOCK_RAW,
socket.getprotobyname("icmp"))
# Delete the methods overrited by the socket initializer to make
# possible defining our own.
for attr in socket._delegate_methods:
try:
delattr(self, attr)
except AttributeError:
pass
def sendto(self, data, flags, addr):
return self._sock.sendto(data, flags, (addr, 1))
icmp = ICMPSocket()
print icmp.sendto('PING', 0, '127.0.0.1')