Использовать Python xmlrpclib с сокетами домена unix?

Я пытаюсь взаимодействовать с supervisord, и я хотел бы поговорить с ним через сокет unix (это среда общего хостинга).

Что я пробовал до сих пор:

import xmlrpclib
server = xmlrpclib.ServerProxy('unix:///path/to/supervisor.sock/RPC2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/xmlrpclib.py", line 1549, in __init__
    raise IOError, "unsupported XML-RPC protocol"
IOError: unsupported XML-RPC protocol

/path/to/supervisor.sock определенно существует. URI вида 'unix:///path/to/supervisor.sock/RPC2' используются supervisord, откуда у меня появилась идея. В документации не обсуждаются сокеты unix: http://docs.python.org/library/xmlrpclib. HTML.

Это возможно? Должен ли я использовать другую библиотеку?


person Marcin    schedule 30.07.2012    source источник


Ответы (4)


xmlrpclib требует, чтобы переданный URL начинался с http или https. Чтобы обойти это, нужно определить собственный транспорт, который игнорирует этот URL-адрес. Вот некоторый код, использующий транспорт от супервизора:

import supervisor.xmlrpc
import xmlrpclib

proxy = xmlrpclib.ServerProxy('http://127.0.0.1',
                               transport=supervisor.xmlrpc.SupervisorTransport(
                                    None, None, serverurl='unix://'+socketpath))

proxy.supervisor.getState()

Если это бесполезно, вот обновленная версия кода, найденная здесь:

class UnixStreamHTTPConnection(httplib.HTTPConnection, object):
    def __init__(self, *args, **kwargs):
        self.socketpath = kwargs.pop('socketpath')
        super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs)

    def connect(self):
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.sock.connect_ex(self.socketpath)

class UnixStreamTransport(xmlrpclib.Transport, object):
    def __init__(self, *args, **kwargs):
        self.socketpath = kwargs.pop('socketpath')
        super(UnixStreamTransport, self).__init__(*args, **kwargs)
person Marcin    schedule 31.07.2012

Вот обновленный пример использования xmlrpclib для общения с руководителем:

import httplib
import socket
import xmlrpclib

class UnixStreamHTTPConnection(httplib.HTTPConnection):
    def connect(self):
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.sock.connect(self.host)

class UnixStreamTransport(xmlrpclib.Transport, object):
    def __init__(self, socket_path):
        self.socket_path = socket_path
        super(UnixStreamTransport, self).__init__()

    def make_connection(self, host):
        return UnixStreamHTTPConnection(self.socket_path)


server = xmlrpclib.Server('http://arg_unused', transport=UnixStreamTransport("/var/run/supervisor.sock"))
print(server.supervisor.getState())

Как уже упоминалось, мы должны указать фиктивный URL-адрес с http:// или https://, а затем указать собственный транспорт для обработки сокета домена.

person Adaptation    schedule 23.05.2014

Моя версия для python3, подготовленная из версий выше.

from http.client import HTTPConnection
import socket
from xmlrpc import client

class UnixStreamHTTPConnection(HTTPConnection):
    def connect(self):
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.sock.connect(self.host)

class UnixStreamTransport(client.Transport, object):
    def __init__(self, socket_path):
        self.socket_path = socket_path
        super(UnixStreamTransport, self).__init__()

    def make_connection(self, host):
        return UnixStreamHTTPConnection(self.socket_path)

proxy = client.ServerProxy('http://localhost', transport=UnixStreamTransport("/var/run/supervisor.sock"))

print(proxy.supervisor.getState())
person Pavel Cisar    schedule 17.07.2018

Смешивая ответы выше, вот что работает для меня...

import httplib
import socket
import xmlrpclib

class UnixStreamHTTPConnection(httplib.HTTPConnection, object):
    def __init__(self, *args, **kwargs):
        self.socketpath = kwargs.pop('socketpath')
        super(UnixStreamHTTPConnection, self).__init__(*args, **kwargs)

    def connect(self):
        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        self.sock.connect(self.socketpath)

class UnixStreamTransport(xmlrpclib.Transport, object):
    def __init__(self, *args, **kwargs):
        self.socketpath = kwargs.pop('socketpath')
        super(UnixStreamTransport, self).__init__(*args, **kwargs)

    def make_connection(self, host):
        return UnixStreamHTTPConnection(host, socketpath=self.socketpath)

server = xmlrpclib.ServerProxy('http://arg_unused', transport=UnixStreamTransport(socketpath="path/to/supervisor.sock"))
print server.supervisor.getState()
person petre    schedule 14.07.2017