【问题标题】:Google Cloud Storage File System, Python Package Error: AttributeError: 'GCSFile' object has no attribute 'gcsfs'谷歌云存储文件系统,Python 包错误:AttributeError: \'GCSFile\' object has no attribute \'gcsfs\'
【发布时间】:2022-08-20 00:23:38
【问题描述】:

我正在尝试运行一个 python 代码,它将从源 URL 下载数据块并将其流式传输到目标云存储 blob。 它在独立电脑、本地功能等中运行良好。 但是当我尝试使用 GCP Cloud RUN 时,它会抛出奇怪的错误。

AttributeError: \'GCSFile\' object has no attribute \'gcsfs\'

完全错误:

Traceback (most recent call last):
  File \"/home/<user>/.local/lib/python3.9/site-packages/fsspec/spec.py\", line 1683, in __del__
    self.close()
  File \"/home/<user>/.local/lib/python3.9/site-packages/fsspec/spec.py\", line 1661, in close
    self.flush(force=True)
  File \"/home/<user>/.local/lib/python3.9/site-packages/fsspec/spec.py\", line 1527, in flush
    self._initiate_upload()
  File \"/home/<user>/.local/lib/python3.9/site-packages/gcsfs/core.py\", line 1443, in _initiate_upload
    self.gcsfs.loop,
AttributeError: \'GCSFile\' object has no attribute \'gcsfs\'

它消耗了我的一周,任何帮助或方向都非常感谢,在此先感谢。

实际使用的代码:

from flask import Flask, request
import os
import gcsfs
import requests

app = Flask(__name__)


@app.route(\'/urltogcs\')
def urltogcs():
    try:
        os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"] = \"secret.json\"
        gcp_file_system = gcsfs.GCSFileSystem(project=\'<project_id>\')
        session = requests.Session()
        url = request.args.get(\'source\', \'temp\')
        blob_path = request.args.get(\'destination\', \'temp\')
        with session.get(url, stream=True) as r:
            r.raise_for_status()
            with gcp_file_system.open(blob_path, \'wb\') as f_obj:
                for chunk in r.iter_content(chunk_size=1024 * 1024):
                    f_obj.write(chunk)
        return f\'Successfully downloaded from {url} to {blob_path} :)\'
    except Exception as e:
        print(\"Failure\")
        print(e)
        return f\'download failed for  {url} :(\'


if __name__ == \"__main__\":
    app.run(debug=True, host=\"0.0.0.0\", port=int(os.environ.get(\"PORT\", 8080)))
  • 请显示您正在使用的代码。
  • 感谢您的快速回复,我刚刚将代码添加到实际问题中。
  • 你不应该os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"]=\"secret.json\"gcsfs 似乎使用应用程序默认凭据(请参阅Credentials),因此此步骤是不必要的,并且可以节省您将服务帐户机密放入部署工件(这是不安全的)。该代码将使用 Cloud Run 服务的(默认)身份,因此请确保您将其权限授予 GCS。
  • 当您在本地运行代码时(删除该语句后),您可以export GOOGLE_APPLICATION_CREDENTIALS=/path/to/secret.json 然后运行您的代码,应用程序默认凭据也将以这种方式验证您的代码。
  • 完全同意@DazWilkin。避免使用显式机密。更喜欢本地环境变量,而不是云中的任何内容(您拥有为库提供凭据的元数据服务器)。您还可以通过执行gcloud auth application-default login 来避免使用密钥文件,以使用您的凭据。清理你的代码,它应该更清晰、更简单、更容易调试。

标签: google-cloud-platform python-3.7 google-cloud-run


【解决方案1】:

您的代码(带有提议的更改)对我有用:

main.py:

from flask import Flask, request
import os
import gcsfs
import requests

app = Flask(__name__)

project = os.getenv("PROJECT")
port = os.getenv("PORT", 8080)

@app.route('/urltogcs')
def urltogcs():
    try:
        gcp_file_system = gcsfs.GCSFileSystem(project=project)
        session = requests.Session()
        url = request.args.get('source', 'temp')
        blob_path = request.args.get('destination', 'temp')
        with session.get(url, stream=True) as r:
            r.raise_for_status()
            with gcp_file_system.open(blob_path, 'wb') as f_obj:
                for chunk in r.iter_content(chunk_size=1024 * 1024):
                    f_obj.write(chunk)
        return f'Successfully downloaded from {url} to {blob_path} :)'
    except Exception as e:
        print("Failure")
        print(e)
        return f'download failed for  {url}


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(port))

笔记该代码需要来自不理想环境的project。如果gcsfs.GCSFileSystem 不需要project 会更好。或者,project 可以从 Google 的元数据服务中获取。为了方便(!),我使用环境设置它。

requirements.txt:

Flask==2.2.2
gcsfs==2022.7.1
gunicorn==20.1.0

Dockerfile:

FROM python:3.10-slim

ENV PYTHONUNBUFFERED True

ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

RUN pip install --no-cache-dir -r requirements.txt

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app

bash 脚本:

BILLING="[YOUR-BILLING]"
PROJECT="[YOUR-PROJECT]"
REGION="[YOUR-REGION]"
BUCKET="[YOUR-BUCKET]"

# Create Project
gcloud projects create ${PROJECT}

# Associate with Billing Account
gcloud beta billing projects link ${PROJECT} \
--billing-account=${BILLING}

# Enabled services
SERVICES=(
  "artifactregistry"
  "cloudbuild"
  "run"
)
for SERVICE in ${SERVICES[@]}
do
  gcloud services enable ${SERVICE}.googleapis.com \
  --project=${PROJECT}
done

# Create Bucket
gsutil mb -p ${PROJECT} gs://${BUCKET}

# Service Account
ACCOUNT=tester
EMAIL=${ACCOUNT}@${PROJECT}.iam.gserviceaccount.com

# Create Service Account
gcloud iam service-accounts create ${ACCOUNT} \
--project=${PROJECT}

# Create Service Account key
gcloud iam service-accounts keys create ${PWD}/${ACCOUNT}.json \
--iam-account=${EMAIL} \
--project=${PROJECT}

# Ensure Service Account can write to storage
gcloud projects add-iam-policy-binding ${PROJECT} \
--role=roles/storage.admin \
--member=serviceAccount:${EMAIL}

# Only needed for local testing
export GOOGLE_APPLICATION_CREDENTIALS=${PWD}/${ACCOUNT}.json

# Deploy Cloud Run service
# Run service as Service Account
NAME="urltogcs"
gcloud run deploy ${NAME} \
--source=${PWD}  \
--set-env-vars=PROJECT=${PROJECT} \
--no-allow-unauthenticated \
--service-account=${EMAIL} \
--region=${REGION} \
--project=${PROJECT}

# Grab the Cloud Run service's endpoint
ENDPOINT=$(gcloud run services describe ${NAME} \
--region=${REGION} \
--project=${PROJECT} \
--format="value(status.url)")

# Cloud Run service requires auth
TOKEN=$(gcloud auth print-identity-token)

# This page
SRC="https://stackoverflow.com/questions/73393808/"

# Generate a GCS Object name by epoch
DST="gs://${BUCKET}/$(date +%s)"

curl \
--silent \
--get \
--header "Authorization: Bearer ${TOKEN}" \
--data-urlencode "source=${SRC}" \
--data-urlencode "destination=${DST}" \
--write-out '%{response_code}' \
--output /dev/null \
${ENDPOINT}/urltogcs

产量OK:

200

和:

gsutil ls gs://${BUCKET}

gs://${BUCKET}/1660780270

【讨论】:

  • 真的很欣赏这些标准,但我仍然无法理解和/或隔离问题。对我来说,它仍然是同样的错误。
猜你喜欢
  • 2021-11-08
  • 2022-12-01
  • 2022-12-03
  • 2018-02-05
  • 2014-12-20
  • 2021-03-05
  • 2017-10-21
  • 1970-01-01
  • 2012-02-29
相关资源
最近更新 更多