How to create a socket.socket() object from a socket fd?

Grant Edwards grant.b.edwards at gmail.com
Sat Jan 21 17:28:42 EST 2017


Given a Unix file discriptor for an open TCP socket, I can't figure
out how to create a python 2.7 socket object like those returned by
socket.socket() 

Based on the docs, one might think that socket.fromfd() would do that
(since the docs say that's what it does):

Quoting https://docs.python.org/2/library/socket.html

 the socket() function returns a socket object

 [...]  
 
 socket.socket([family[, type[, proto]]])
    Create a new socket using the given address family[...]
 
 [...]
    
 socket.fromfd(fd, family, type[, proto])
    Duplicate the file descriptor fd (an integer as returned by a file
    object’s fileno() method) and build a socket object from the
    result. 

But it doesn't work as described -- the docs apprently use the term
"socket object" to refer to two different things.
    
IOW, a "socket object" is a different type than a "socket object".

Here's what a "socket object" returned by socket.socket() looks like:

  repr(osock):
  <socket._socketobject object at 0x7f701948f520>
  
  dir(osock):
  ['__class__', '__delattr__', '__doc__', '__format__',
  '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
  '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
  '__sizeof__', '__slots__', '__str__', '__subclasshook__',
  '__weakref__', '_sock', 'accept', 'bind', 'close', 'connect',
  'connect_ex', 'dup', 'family', 'fileno', 'getpeername', 'getsockname',
  'getsockopt', 'gettimeout', 'listen', 'makefile', 'proto', 'recv',
  'recv_into', 'recvfrom', 'recvfrom_into', 'send', 'sendall', 'sendto',
  'setblocking', 'setsockopt', 'settimeout', 'shutdown', 'type']

[If asked, I would call that a "socket._socketobject object".]

Here's what a "socket object" returned from socket.fromfd() object looks like:

  repr(sock):
  <socket object, fd=6, family=2, type=1, protocol=0>
  
  dir(sock):
  ['__class__', '__delattr__', '__doc__', '__format__',
  '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__',
  '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__',
  '__subclasshook__', 'accept', 'bind', 'close', 'connect',
  'connect_ex', 'dup', 'family', 'fileno', 'getpeername', 'getsockname',
  'getsockopt', 'gettimeout', 'listen', 'makefile', 'proto', 'recv',
  'recv_into', 'recvfrom', 'recvfrom_into', 'send', 'sendall', 'sendto',
  'setblocking', 'setsockopt', 'settimeout', 'shutdown', 'timeout',
  'type']

They're different types.

[That one I sould all a "socket object".]  

Note that the socket.socket() object has a '_sock' attribute, which
appears to contain an object like that returned by socket.fromfd():

  repr(osock._sock):
  <socket object, fd=4, family=2, type=1, protocol=0>

That prompts a question: given a "socket object" as returned by
socket.fromfd(), how does one create a "socket._socketobject object"
as returned by socket.socket()? 

It also makes one wonder why doesn't socket.fromfd() return the same
type of object as socke.socket()?  In what context would you want the
type of object returned from socket.fromrd() instead of that returned
by socket.socket()?

[An ssl context will wrap the latter, but not the former, in case
you're wondering why I care about the difference.]

Also, I passed socket.fromfd fd==5, and the resulting "socket object"
is using fd==6. Why does socket.fromfd() duplicate the fd?  If I
wanted the file descriptor duplicated, I would have do it myself!
[Yes, I know the documentation _says_ it will duplicate the fd, I just
don't understand why, and I think it a bad idea.]

-- 
Grant



More information about the Python-list mailing list