我正在开发一个用Python(标准环境(编写的Google App Engine应用程序,我需要将开发服务器环境中的一些其他模块列入白名单。
我已经在 appengine_config 文件中使用此代码很长时间了,并且效果很好:
from google.appengine.tools.devappserver2.python import sandbox
sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']
正如这个问题所回答的,前段时间谷歌云SDK更新了,之前的导入导致了导入错误。导入只需更改为:
from google.appengine.tools.devappserver2.python.runtime import sandbox
通过此更改,一切再次运行良好,直到我将 Cloud SDK 更新到版本:186.0.0。
现在似乎有一个"SandboxAccessPreventionImportHook"类已添加到沙盒模块中,因此无法从App Engine应用程序导入。这是应用程序引发的错误:
ImportError: Importing the devappserver sandbox module (google.appengine.tools.devappserver2.python.runtime.sandbox) from user application code is not permitted.
有没有人知道如何绕过它?还是有另一种方法可以将开发服务器环境中的模块列入白名单?
谢谢!!!
我们遇到了与 OP 完全相同的问题,但不幸的是 Alex 的解决方案对我们不起作用。
虽然这是一个非常非常黑客的解决方案,但这正是对我们有用的。请注意,沙盒的修改必须在更新后重做。
sandbox.py 修改位于 {appengine_sdk_dir}/google/appengine/tools/devappserver2/python/runtime/sandbox.py
并将 Alex 的第一个示例中的_ssl
和_socket
添加到_WHITE_LIST_C_MODULES
列表中。
_WHITE_LIST_C_MODULES = [
// keep existing items
'_ssl',
'_socket'
]
然后,我们从appengine_config.py
中删除了导入和沙盒覆盖。
vendor.add('lib')
if os.environ.get('SERVER_SOFTWARE', '').startswith('Development'):
import imp
import os.path
import inspect
# 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)
# handle requests_toolbelt's monkeypatch as you see fit.
让我们希望有一天不再需要这样做!
上下文
所以对我来说,这个问题的根源是dev_appserver.py
无法发送出站https请求/套接字。
然后的解决方案是把它放在我的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()
今天我升级了我的云 sdk 并开始获得
ImportError: Importing the devappserver sandbox module (google.appengine.tools.devappserver2.python.runtime.sandbox) from user application code is not permitted.
如果我删除_WHITE_LIST_C_MODULES
的东西,那么在使用python请求库发出出站https请求时会出现此错误:
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
然后我在这个问题中找到了堆栈跟踪https://github.com/requests/requests/issues/4078这似乎表明这仅在 python-requests 版本 2.16.0 之后才开始发生
溶液
我所有的第三方库都安装到我的项目根目录中一个名为 lib
的文件夹中,使用
pip install -t lib
现在,我有lib
和localhost_libs
,我做到了:
pip install -t localhost_libs requests==2.16
我的appengine_config.py现在有这个:
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"
编辑:修改的解决方案以使用pkg_resources
,不需要prod_libs
文件夹
沙盒模块的位置已移动到运行时模块中。
from google.appengine.tools.devappserver2.python import runtime
runtime.sandbox._WHITE_LIST_C_MODULES += ['_ssl', '_socket']
@karloskar提到的方式解决了我的情况。
但是,在我修改 sandbox.py 以允许WHITE_LIST_ssl和_socket后,我遇到了另一个库导入问题 - 导入错误:没有名为google.auth的模块。
对于谁也得到了上面的google.auth导入错误,您可以考虑像下面这样更新您的appengine_config.py
。这就是解决我的导入问题的方法。
# appengine_config.py
import os
import google
from google.appengine.ext import vendor
lib_directory = os.path.dirname(__file__) + '/lib'
# Change where to find the google package (point to the lib/ directory)
google.__path__ = [os.path.join(lib_directory, 'google')] + google.__path__
# Add any libraries install in the "lib" folder.
vendor.add(lib_directory)
参考文献1:App Engine 在 dev_appserver.py 中找不到 google.auth 文件
参考文献2:https://github.com/GoogleCloudPlatform/google-auth-library-python/issues/169#issuecomment-315417916