我正在尝试使用以此处的 python 示例代码为模型的 python 脚本将 CSV 文件加载到 BigQuery:https ://developers.google.com/bigquery/docs/developers_guide
但是当我尝试使用 REST API 加载表时遇到以下错误:
{'status': '200', 'content-length': '1492', 'expires': 'Fri, 01 Jan 1990 00:00:00 GMT', 'server': 'HTTP Upload Server Built on Jun 14 2012 02:12:09 (1339665129)', 'etag': '"tcivyOj9QvKAbuEJ5MEMf9we85w/-mxYhUDjvvydxcebR8fXI6l_5RQ"', 'pragma': 'no-cache', 'cache-control': 'no-cache, no-store, must-revalidate', 'date': 'Fri, 06 Jul 2012 22:30:55 GMT', 'content-type': 'application/json'}
{
"kind": "bigquery#job",
"etag": "\"tcivyOj9QvKAbuEJ5MEMf9we85w/-mxYhUDjvvydxcebR8fXI6l_5RQ\"",
"id": "firespotter.com:firespotter:job_d6b99265278b4c0da9c3033acf39d6b2",
"selfLink": "https://www.googleapis.com/bigquery/v2/projects/firespotter.com:firespotter/jobs/job_d6b99265278b4c0da9c3033acf39d6b2",
"jobReference": {
"projectId": "firespotter.com:firespotter",
"jobId": "job_d6b99265278b4c0da9c3033acf39d6b2"
},
"configuration": {
"load": {
"schema": {
"fields": [
{
"name": "date",
"type": "STRING"
},
{
"name": "time",
"type": "STRING"
},
{
"name": "call_uuid",
"type": "STRING"
},
{
"name": "log_level",
"type": "STRING"
},
{
"name": "file_line",
"type": "STRING"
},
{
"name": "message",
"type": "STRING"
}
]
},
"destinationTable": {
"projectId": "385479794093",
"datasetId": "telephony_logs",
"tableId": "table_name"
},
"createDisposition": "CREATE_IF_NEEDED",
"writeDisposition": "WRITE_TRUNCATE",
"encoding": "UTF-8"
}
},
"status": {
"state": "DONE",
"errorResult": {
"reason": "notFound",
"message": "Not Found: Dataset 385479794093:telephony_logs"
},
"errors": [
{
"reason": "notFound",
"message": "Not Found: Dataset 385479794093:telephony_logs"
}
]
}
}
错误“385479794093”中列出的projectId不是我传入的projectId,是“项目号”。projectId 应该是“firespotter.com:firespotter”:
{
"kind": "bigquery#datasetList",
"etag": "\"tcivyOj9QvKAbuEJ5MEMf9we85w/ZMa8z6LKMgWZIqLWh3ti2SsSs4g\"",
"datasets": [
{
"kind": "bigquery#dataset",
"id": "firespotter.com:firespotter:telephony_logs",
"datasetReference": {
"datasetId": "telephony_logs",
"projectId": "firespotter.com:firespotter"
}
}
]
}
当我在三个不同的地方传递正确的值时,为什么 REST API 坚持提供自己不正确的 projectId?还有其他地方需要我传入或设置项目ID吗?
作为参考,这里是相关的代码片段:
PROJECT = 'firespotter.com:firespotter'
DATASET = 'telephony_logs'
FLOW = OAuth2WebServerFlow(
client_id='385479794093.apps.googleusercontent.com',
client_secret='<a_secret_here>',
scope='https://www.googleapis.com/auth/bigquery',
user_agent='firespotter-upload-script/1.0')
def loadTable(http, projectId, datasetId, tableId, file_path, replace=False):
url = "https://www.googleapis.com/upload/bigquery/v2/projects/" + projectId + "/jobs"
# Create the body of the request, separated by a boundary of xxx
mime_data = ('--xxx\n' +
'Content-Type: application/json; charset=UTF-8\n' + '\n' +
'{\n' +
' "projectId": "' + projectId + '",\n' +
' "configuration": {\n' +
' "load": {\n' +
' "schema": {\n' +
' "fields": [\n' +
' {"name":"date", "type":"STRING"},\n' +
' {"name":"time", "type":"STRING"},\n' +
' {"name":"call_uuid", "type":"STRING"},\n' +
' {"name":"log_level", "type":"STRING"},\n' +
' {"name":"file_line", "type":"STRING"},\n' +
' {"name":"message", "type":"STRING"}\n' +
' ]\n' +
' },\n' +
' "destinationTable": {\n' +
' "projectId": "' + projectId + '",\n' +
' "datasetId": "' + datasetId + '",\n' +
' "tableId": "' + tableId + '"\n' +
' },\n' +
' "createDisposition": "CREATE_IF_NEEDED",\n' +
' "writeDisposition": "' + ('WRITE_TRUNCATE' if replace else 'WRITE_APPEND') + '",\n' +
' "encoding": "UTF-8"\n' +
' }\n' +
' }\n' +
'}\n' +
'--xxx\n' +
'Content-Type: application/octet-stream\n' +
'\n')
# Append data from the specified file to the request body
f = open(file_path, 'r')
header_line = f.readline() # skip header line
mime_data += f.read()
# Signify the end of the body
mime_data += ('--xxx--\n')
headers = {'Content-Type': 'multipart/related; boundary=xxx'}
resp, content = http.request(url, method="POST", body=mime_data, headers=headers)
print str(resp) + "\n"
print content
# --- Main ----------------------------------------------
def main(argv):
csv_path = args[0]
# If the credentials don't exist or are invalid, run the native client
# auth flow. The Storage object will ensure that if successful the good
# credentials will get written back to a file.
storage = Storage('bigquery2_credentials.dat') # Choose a file name to store the credentials.
credentials = storage.get()
if credentials is None or credentials.invalid:
credentials = run(FLOW, storage)
# Create an httplib2.Http object to handle our HTTP requests and authorize it
# with our good credentials.
http = httplib2.Http()
http = credentials.authorize(http)
loadTable(http, PROJECT, DATASET, 'table_name', csv_path, replace=True)
if __name__ == '__main__':
main(sys.argv)