Context
So for me the root of this issue was the dev_appserver.py
's inability to send outbound https requests / sockets.
The solution then was to put this in my appengine_config.py
:
vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
import imp
import os.path
import inspect
try:
from google.appengine.tools.devappserver2.python import sandbox
except ImportError:
from google.appengine.tools.devappserver2.python.runtime import sandbox
sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']
# Use the system socket.
real_os_src_path = os.path.realpath(inspect.getsourcefile(os))
psocket = os.path.join(os.path.dirname(real_os_src_path), 'socket.py')
imp.load_source('socket', psocket)
else:
# Doing this on dev_appserver/localhost seems to cause outbound https requests to fail
import requests
from requests_toolbelt.adapters import appengine as requests_toolbelt_appengine
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt_appengine.monkeypatch()
Today I upgraded my cloud sdk and started getting
ImportError: Importing the devappserver sandbox module (google.appengine.tools.devappserver2.python.runtime.sandbox) from user application code is not permitted.
If I remove the _WHITE_LIST_C_MODULES
stuff, I then get this error when using the python requests library to make outbound https requests:
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch.py", line 293, in fetch
return rpc.get_result()
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch.py", line 413, in _get_fetch_result
rpc.check_success()
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_stub_map.py", line 579, in check_success
self.__rpc.CheckSuccess()
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/apiproxy_rpc.py", line 157, in _WaitImpl
self.request, self.response)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/ext/remote_api/remote_api_stub.py", line 222, in MakeSyncCall
self._MakeRealSyncCall(service, call, request, response)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/ext/remote_api/remote_api_stub.py", line 241, in _MakeRealSyncCall
request_pb.set_request(request.Encode())
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 103, in Encode
self.Output(e)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 347, in Output
self.OutputUnchecked(e)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch_service_pb.py", line 481, in OutputUnchecked
out.putDouble(self.deadline_)
File "/Users/alexindaco/google-cloud-sdk/platform/google_appengine/google/net/proto/ProtocolBuffer.py", line 592, in putDouble
a.fromstring(struct.pack("<d", v))
error: required argument is not a float
I then found that stack trace in this issue
https://github.com/requests/requests/issues/4078
which seemed to indicate that this only started happening after python-requests version 2.16.0
Solution
All my third party libs were installed to a folder in my project root called lib
using
pip install -t lib
Now, I have lib
& localhost_libs
and I did:
pip install -t localhost_libs requests==2.16
My appengine_config.py now has this instead:
vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
vendor.add('localhost_libs')
import pkg_resources
pkg_resources.require("requests==2.16.0")
import requests
print "requests.__version__", requests.__version__
from requests_toolbelt.adapters import appengine as requests_toolbelt_appengine
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt_appengine.monkeypatch()
print "Appengine config done"
Edit: Modified solution to use pkg_resources
and not require a prod_libs
folder