我一直在开发一个Flask应用程序,它运行得很好。我本来打算把我的应用程序上传到谷歌的应用程序引擎,但我遇到了麻烦。为了创建Google的API服务,我需要读取一个文件,我使用/tmp/来读取它,但它不起作用。这个文件是token_sheets_v4.pickle
import os
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
from google.auth.transport.requests import Request
def Create_Service(client_secret_file, api_name, api_version, *scopes):
print(client_secret_file, api_name, api_version, scopes, sep='-')
CLIENT_SECRET_FILE = client_secret_file
API_SERVICE_NAME = api_name
API_VERSION = api_version
SCOPES = [scope for scope in scopes[0]]
print(SCOPES)
cred = None
if os.path.exists(pickle_file):
with open('/tmp/token_sheets_v4.pickle', 'rb') as token:
cred = pickle.load(token)
if not cred or not cred.valid:
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
cred = flow.run_local_server()
with open(pickle_file, 'wb') as token:
pickle.dump(cred, token)
try:
service = build(API_SERVICE_NAME, API_VERSION, credentials=cred)
print(API_SERVICE_NAME, 'service created successfully')
return service
except Exception as e:
print('Unable to connect.')
print(e)
return None
def convert_to_RFC_datetime(year=1900, month=1, day=1, hour=0, minute=0):
dt = datetime.datetime(year, month, day, hour, minute, 0).isoformat() + 'Z'
return dt
特别是,这部分给我带来了麻烦(FileNotFoundError:[Erno 2]没有这样的文件或目录:"/tmp/token_sheets_v4.pickle"(:
with open('/tmp/token_sheets_v4.pickle', 'rb') as token:
cred = pickle.load(token)
我已经尝试将这些信息放在app.yaml
上,但我只有在转到我的应用时才能下载文件(token_sheets_v4.pickle(
entrypoint: gunicorn -b :$PORT main:app
handlers:
- url: /
static_files: token_sheets_v4.pickle
upload: token_sheets_v4.pickle
如果有人能帮忙,我会非常感激,谢谢
由于您将token_sheets_v4.pickle视为静态文件,我认为您的app.yaml文件应该类似
- url: /tmp/token_sheets_v4.pickle
static_files: token_sheets_v4.pickle
upload: token_sheets_v4.pickle
但即使是上述内容也是错误的,因为/tmp/
是一个临时目录。正如文档所说,该目录中的所有文件都存储在实例的RAM中,因此写入/tmp会占用系统内存。
所以最后,我认为你的app.yaml
实际上应该是
- url: /token_sheets_v4.pickle
static_files: token_sheets_v4.pickle
upload: token_sheets_v4.pickle
然后你的代码应该直接读取文件,而不是引用/tmp/
您不希望使用静态文件来执行此操作。将文件token_sheets_v4.pickle
与您的代码放在一起,当您部署代码时,此文件也将上载。
然后,您的Python代码可以像打开任何其他文件一样打开该文件。一个有用的技巧是使用Python文件的__file__
属性来帮助指定文件的路径。
假设该文件与code.py
位于同一目录中。在code.py
中,您可以打开如下文件:
fn = os.path.dirname(__file__) + "/token_sheets_v4.pickle"
with open(fn, 'rb') as f:
...
我经常这样做,效果很好。
因此,在解决这个问题一段时间后,我发现最明智的解决方案是阅读谷歌应用程序引擎的文档,就像用户nocommandline建议的那样。阅读这些文档有助于我理解GAE与正确运行应用程序的环境一起工作;适当地";我的意思是,你可以在不设置特定环境的情况下运行应用程序,但这样做会给你更多的选择,比如在这种情况下,读取/写入文件。根据我的理解,我将环境视为在GAE上运行应用程序的一组属性。环境用于确定允许您的应用程序使用的特定资源量,例如http请求超时。那么,你是如何设置环境的呢?根据文档(python(,您必须在app.yaml
文件上设置环境(标准或灵活(。
我发现我最好的选择是标准环境,所以我的最终代码是:
entrypoint: gunicorn -t 3600 -b :$PORT main:app
env_variables:
GAE_ENV: "standard"
为了阅读,我不再需要tmp
,但为了写作,我使用了tmp
。如果您不能理解我的回答,请随时留言