python-magento
python-magento copied to clipboard
SOCK_STREAM Error
Occasionally when trying to initiate an API call / or the API (not sure which at present) I get the following:
Traceback (most recent call last):
File "sales_note_add.py", line 109, in <module>
main()
File "sales_note_add.py", line 87, in main
orderStatus = get_order(orderId)
File "sales_note_add.py", line 56, in get_order
order = mage.sales_order.info(order_id)
File "/Users/mmuser/Documents/magento19-api/magento/__init__.py", line 142, in call_method
return self._client.call(self._session_id, path, args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1240, in __call__
return self.__send(self.__name, args)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1599, in __request
verbose=self.__verbose
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1280, in request
return self.single_request(host, handler, request_body, verbose)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1308, in single_request
self.send_content(h, request_body)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1456, in send_content
connection.endheaders(request_body)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1049, in endheaders
self._send_output(message_body)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 893, in _send_output
self.send(msg)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 855, in send
self.connect()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1266, in connect
HTTPConnection.connect(self)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 832, in connect
self.timeout, self.source_address)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 557, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known
I believe this is where our web server has an issue processing the request and throws an error.
It would be good to build into the magento code some form of error handling for broken connections / calls so they are always handled with a retry(?) so its all rolled up in the API call rather than writing it into the functions calling the API (one place for the connection and error handling)
I will try to fix this in the near future but if anyone has noticed this issue and fixed it already then superb!
I can replicate these errors by disconnecting from the network and attempting to get a session with magento.
I'm not sure on the best way to handle this exception.
one idea is to enclose each call in a While clause and just keep attempting - example:
while True:
try:
orderdetails = magento.sales_order.list(list_info)
except Exception as e:
continue
break
or an example in the actual module
def __init__(self, host, port, api_user, api_key, path=DEFAULT_XMLRPC_PATH,
allow_none=False, verbose=False, proto='http'):
"""Logs the client into Magento's API and discovers methods available
to it. Throws an exception if logging in fails.
"""
self._api_user = api_user
self._api_key = api_key
self._host = host
self._port = str(port)
self._uri = '{}://{}:{}/{}'.format(proto, host, port, path.strip('/'))
While True:
try:
self._client = xmlrpclib.ServerProxy(
self._uri, allow_none=allow_none, verbose=verbose)
self.login()
except Exception as e:
print(str(e))
continue
break
This example is ok, but could just end up stuck (i've thrown it round one of my own calls for clarity)
Possibly add it into a retry range (attempt it x times?)
Any thoughts appreciated as it would be nice to solve the issue in the module, rather than every time in the different code bases it may be used in.
Alex
I would add a class-level variable max_retries, which the user can set on his instance of the api (or on the class if you need it active at the time you initialize the api.) With special cases 0 for no retries and -1 for infinite retries. And I would default this to 0 so as not to change the default behavior as it is now.
Bernard
On 30 July 2015 at 21:35, Bobspadger [email protected] wrote:
I can replicate these errors by disconnecting from the network and attempting to get a session with magento.
I'm not sure on the best way to handle this exception.
one idea is to enclose each call in a While clause and just keep attempting - example:
while True: try: orderdetails = magento.sales_order.list(list_info) except Exception as e: continue break
or an example in the actual module
def __init__(self, host, port, api_user, api_key, path=DEFAULT_XMLRPC_PATH, allow_none=False, verbose=False, proto='http'): """Logs the client into Magento's API and discovers methods available to it. Throws an exception if logging in fails. """ self._api_user = api_user self._api_key = api_key self._host = host self._port = str(port) self._uri = '{}://{}:{}/{}'.format(proto, host, port, path.strip('/')) While True: try: self._client = xmlrpclib.ServerProxy( self._uri, allow_none=allow_none, verbose=verbose) self.login() except Exception as e: print(str(e)) continue breakThis example is ok, but could just end up stuck (i've thrown it round one of my own calls for clarity)
Possibly add it into a retry range (attempt it x times?)
Any thoughts appreciated as it would be nice to solve the issue in the module, rather than every time in the different code bases it may be used in.
Alex
— Reply to this email directly or view it on GitHub https://github.com/bernieke/python-magento/issues/2#issuecomment-126450335 .
Something like
class MagentoAPI: retries = 0
def init(self): retry = -1 while retry < retries: connect to magento..... retry += 1
crap example but is this what you are anticipating ?
hmm I can't add a class level variable and effect it because of the init statement.
(clipped to keep it neat)
class MagentoAPI(object):
"""
Adding in some ability to deal with errors as they occur in the magento module, rather than each time in any higher code
max_retries = x where x is number of attempts
Special cases:
0 = no retries - first attempt or death
-1 = infinite , keep going baby!
"""
max_retries = 0 # keep the behaviour of 1 try and then die
def __init__(self, host, port, api_user, api_key, path=DEFAULT_XMLRPC_PATH,
allow_none=False, verbose=False, proto='http'):
if I then attempt
m = MagentoAPI()
I can't create the object as it needs all the credentials.
If I put the max_retries into the __init__ its no longer class level and can not be adjusted later example: m.max_retries=10
or am I confusing myself ?
brain freeze evening
magento_api.py
snip:
DEFAULT_XMLRPC_PATH = '/api/xmlrpc'
# Default our max_retries to 0 to keep with the original handling of this module
MAX_RETRIES = 0
snip:
def __init__(self, host, port, api_user, api_key, path=DEFAULT_XMLRPC_PATH,
allow_none=False, verbose=False, proto='http', max_retries=MAX_RETRIES):
"""Logs the client into Magento's API and discovers methods available
to it. Throws an exception if logging in fails.
"""
self.max_retries = max_retries
will work on this some more tomorrow
I did in fact mean adding it as a class variable (as in your first snippet.)
You then set it either by doing:
m = MagentoAPI(**connection_arguments)
m.max_retries = 3
Or, if you want the max_retries while connecting as well:
MagentoAPI.max_retries = 3
m = MagentoAPI(**connection_arguments)
The reason I'd rather not see max_retries in the init, is because it's not required to setup the connection. (It's not an argument to xmlrpclib.ServerProxy.)
The normal paradigm would be to have the __init__take things like max_retries, and then have a separate connect method which takes the connection arguments. But doing that now would break backwards compatibility, so the second best way to go is to make extraneous things like max_retries class variables.
Easiest way to replicate is to provide an invalid host name. I was supplying the host as 'http://domainname.com' instead of 'domainname.com'. This triggers the same failure path.