【问题标题】:Accessing data in blob object from download_as_string in Python从 Python 中的 download_as_string 访问 blob 对象中的数据
【发布时间】:2019-10-21 02:52:25
【问题描述】:

我正在尝试访问和修改从 Google Cloud Functions 中的 Google Cloud Storage 提取的换行 JSON 文件中的数据。尽管不是 JSON 中的数据,但结果始终显示为数字。

我看到 blob 对象的 download_as_string() 返回字节 (https://googleapis.github.io/google-cloud-python/latest/_modules/google/cloud/storage/blob.html#Blob.download_as_string) 但在我看到的任何引用中,每个人都可以正常访问他们的数据。

我在 Cloud Functions 中执行此操作,但我认为我的问题适用于任何 GCP 工具。

我下面的示例应该加载换行 JSON 数据,将其添加到列表中,选择前两个字典条目,转换回换行 JSON 并输出到 GCS 上的 JSON 文件。下面列出了示例、代码和错误输出。

换行 JSON 输入示例

{"Website": "Google", "URL": "Google.com", "ID": 1}
{"Website": "Bing", "URL": "Bing.com", "ID": 2}
{"Website": "Yahoo", "URL": "Yahoo.com", "ID": 3}
{"Website": "Yandex", "URL": "Yandex.com", "ID": 4}

云函数中的代码

import requests
import json
import csv
from datetime import datetime, timedelta
import sys
from collections import OrderedDict
import os
import random

from google.cloud import bigquery
from google.cloud import storage

def importData(request, execution):
    # Read the data from Google Cloud Storage
    read_storage_client = storage.Client()

    # Set buckets and filenames
    bucket_name = "sample_bucket"
    filename = 'sample_json_output.json'

    # get bucket with name
    bucket = read_storage_client.get_bucket('sample_bucket')
    # get bucket data as blob
    blob = bucket.get_blob('sample_json.json')
    # download as string
    json_data = blob.download_as_string()

    # create list 
    website_list = []
    for u,y in enumerate(json_data):
        website_list.append(y)

    # select first two
    website_list = website_list[0:2]

    # Create new-line JSON
    results_ready = '\n'.join(json.dumps(item) for item in website_list)

    # Write the data to Google Cloud Storage
    write_storage_client = storage.Client()

    write_storage_client.get_bucket(bucket_name) \
        .blob(filename) \
        .upload_from_string(results_ready)

sample_json_output.json 文件中的当前输出

123
34

预期输出

{"Website": "Google", "URL": "Google.com", "ID": 1}
{"Website": "Bing", "URL": "Bing.com", "ID": 2}

更新 6/6:如果我直接从 download_to_string blob 写入文件,那么它会完美地写入 JSON 文件,但我需要事先访问内容。

import requests
import json
import csv
from datetime import datetime, timedelta
import sys
from collections import OrderedDict
import os
import random

from google.cloud import bigquery
from google.cloud import storage

def importData(request, execution):

    # Read the data from Google Cloud Storage
    read_storage_client = storage.Client()

    # Set buckets and filenames
    bucket_name = "sample_bucket"
    filename = 'sample_json_output.json'

    # get bucket with name
    bucket = read_storage_client.get_bucket('sample_bucket')

    # get bucket data as blob
    blob = bucket.get_blob('sample_json.json')

    # convert to string
    json_data = blob.download_as_string()


    # Write the data to Google Cloud Storage
    write_storage_client = storage.Client()

    write_storage_client.get_bucket(bucket_name) \
        .blob(filename) \
        .upload_from_string(json_data)

更新 6/6 输出

{"Website": "Google", "URL": "Google.com", "ID": 1}
{"Website": "Bing", "URL": "Bing.com", "ID": 2}
{"Website": "Yahoo", "URL": "Yahoo.com", "ID": 3}
{"Website": "Yandex", "URL": "Yandex.com", "ID": 4}

【问题讨论】:

  • 你的问题是每一行都是一个JSON字典对象。您需要将输入分成几行,然后将每一行视为一个对象。
  • 嘿 John - 我以为我是通过迭代并将每个字典行添加到列表中来做到这一点的。我是不是误会了?
  • 问题是当你下载新行 JSON 文件时,在你将每个字典行迭代成一个列表之前。当您使用单个 JSON 对象 download_as_string() 时,它可以工作,但使用带有单独 JSON 对象的换行 JSON 文件似乎无法读取该文件。我还尝试了 download_to_file() 并尝试使用 ndjson 库读取,但它仍然读取为数字。
  • 嘿 Corinne - 查看我在帖子中的更新。如果我加载换行 json 并将其写回写出,它工作得很好......所以它似乎成功读取了文件。

标签: python google-cloud-platform google-cloud-functions google-cloud-storage blobstore


【解决方案1】:

我能够在下面的代码和新行 JSON 的 ndjson 库中使用与您自己类似的方法获得您想要的结果。

import requests
import json
import ndjson
import csv
from datetime import datetime, timedelta
import sys
from collections import OrderedDict
import os
import random

from google.cloud import bigquery
from google.cloud import storage

def importData(request, execution):

    # Read the data from Google Cloud Storage
    read_storage_client = storage.Client()

    # Set buckets and filenames
    bucket_name = "bucket-name"
    filename = "sample_json_output.json"

    # get bucket with name
    bucket = read_storage_client.get_bucket(bucket_name)

    # get bucket data as blob
    blob = bucket.get_blob("sample_json.json")

    # convert to string
    json_data_string = blob.download_as_string()

    json_data = ndjson.loads(json_data_string)

    list = []
    for item in json_data:
        list.append(item)

    list1 = list[0:2]

    result = ""
    for item in list1:
        result = result + str(item) + "\n"


    # Write the data to Google Cloud Storage
    write_storage_client = storage.Client()

    write_storage_client.get_bucket(bucket_name) \
        .blob(filename) \
        .upload_from_string(result)

【讨论】:

  • 这行得通!我能够操作数据并将其写回。我将阅读更多关于 ndjson 包的信息,以了解更多关于功能的信息。
【解决方案2】:

当您读取 json_data 中的 blob 时,您将获得一个字节对象,当您对其进行迭代时,您将获得每个字符的数字表示。下面是一个从字节对象创建字典列表的示例

json_data                                                                                                                                                                                                 
b'{"Website": "Google", "URL": "Google.com", "ID": 1}\n{"Website": "Bing", "URL": "Bing.com", "ID": 2}\n{"Website": "Yahoo", "URL": "Yahoo.com", "ID": 3}\n{"Website": "Yandex", "URL": "Yandex.com", "ID": 4}\n'

type(json_data)                                                                                                                                                                                           
bytes

website_list = [json.loads(row.decode('utf-8')) for row in json_data.split(b'\n') if row]                                                                                                                 

website_list                                                                                                                                                                                              
[{'Website': 'Google', 'URL': 'Google.com', 'ID': 1},
 {'Website': 'Bing', 'URL': 'Bing.com', 'ID': 2},
 {'Website': 'Yahoo', 'URL': 'Yahoo.com', 'ID': 3},
 {'Website': 'Yandex', 'URL': 'Yandex.com', 'ID': 4}]

【讨论】:

  • 我在 json.loads 行收到以下错误:--- decode raise JSONDecodeError("Extra data", s, end) json.decoder.JSONDecodeError: Extra data: line 1 column 52 ( char 51) --- 这看起来与错误一致。我会探索:stackoverflow.com/questions/21058935/…
猜你喜欢
  • 1970-01-01
  • 2012-06-29
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
相关资源
最近更新 更多