如何使用 /tmp/ 读取 App Engine 上的文件?我得到 [Errno 2] No such file or directory

How to read files on App Engine using /tmp/? I get [Errno 2] No such file or directory

我一直在开发 Flask 应用程序,它运行良好。我打算将我的应用程序上传到 Google 的 App Engine,但我遇到了麻烦。 我需要读取文件以创建 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: [Errno 2] No such file or directory: '/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/是一个临时目录。正如 documentation 所说 - 此目录中的所有文件都存储在实例的 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:
    ...

我经常这样做,效果很好。

因此,在与这个问题斗争了一段时间之后,我发现最聪明的解决方案是 阅读 Google App Engine 的文档,就像用户 nocommandline 所建议的那样。 阅读文档帮助我了解 GAE 可以在 运行 您的应用程序正确运行的环境中工作,“正确地”我的意思是您可以 运行 应用程序而无需设置特定环境,但这样做会给您更多选择,例如在本例中,reading/writing 个文件。根据我的理解,我将环境视为 运行 GAE 上应用程序的一组属性。环境用于确定允许您的应用程序使用的特定资源量,例如 http 请求超时。 而且,无论如何,您如何设置环境? 根据 docs (python),您必须在 app.yaml 文件中设置环境(标准或灵活)。

我发现我最好的选择是标准环境,所以我的最终代码是:

entrypoint: gunicorn -t 3600 -b :$PORT main:app

env_variables:
  GAE_ENV: "standard"

对于阅读,我不再需要 tmp,但对于写作,我使用了 tmp如果您不明白我的回答,请随时发表评论