Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2.7 Google应用程序引擎的BigQuery cron作业凭据_Python 2.7_Google App Engine_Cron_Google Bigquery - Fatal编程技术网

Python 2.7 Google应用程序引擎的BigQuery cron作业凭据

Python 2.7 Google应用程序引擎的BigQuery cron作业凭据,python-2.7,google-app-engine,cron,google-bigquery,Python 2.7,Google App Engine,Cron,Google Bigquery,更新:我已经缩小了问题的范围,所以我删除了不必要的代码和示例: 更新2:在让cron作业每隔12小时运行一段时间后(每次都以成功结束,但没有在BQ中写入任何内容),我们震惊地发现,大约一周后,其中一个cron作业成功地写入了BigQuery,Stackdriver日志表明“此请求导致为您的应用程序启动了一个新进程(…)”,如下所述。以下作业再次停止写入。现在我想知道这是否以某种方式连接到某个缓存的应用程序状态(有一些过期期限)或凭据过期日期,以某种方式阻止在第一次之后进一步写入BigQuery,

更新:我已经缩小了问题的范围,所以我删除了不必要的代码和示例:

更新2:在让cron作业每隔12小时运行一段时间后(每次都以成功结束,但没有在BQ中写入任何内容),我们震惊地发现,大约一周后,其中一个cron作业成功地写入了BigQuery,Stackdriver日志表明“此请求导致为您的应用程序启动了一个新进程(…)”,如下所述。以下作业再次停止写入。现在我想知道这是否以某种方式连接到某个缓存的应用程序状态(有一些过期期限)或凭据过期日期,以某种方式阻止在第一次之后进一步写入BigQuery,但不会导致错误

问题描述:

我正在尝试在App Engine(standard)中设置一个cron作业来查询BigQuery并将数据写回BigQuery(数据集与部署的应用程序位于同一个项目中),cron作业成功执行,但仅在部署后的第一次执行时写入BigQuery,之后它们仍然成功执行,但不写入

我发现的主要区别在于Stackdriver日志,对于正确写入的执行,有额外的调试和信息,对于后续的执行,没有这样的消息:

2018-04-19 04:44:03.933 CEST
Converted retries value: 3 -> Retry(total=3, connect=None, read=None, redirect=None, status=None) (/base/data/home/apps/e~<redacted>/lib/urllib3/util/retry.py:200)
2018-04-19 04:44:04.154 CEST
Making request: POST https://accounts.google.com/o/oauth2/token (/base/data/home/apps/e~<redacted>/lib/google/auth/transport/requests.py:117)
2018-04-19 04:44:04.160 CEST
Starting new HTTPS connection (1): accounts.google.com (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:824)
2018-04-19 04:44:04.329 CEST
https://accounts.google.com:443 "POST /o/oauth2/token HTTP/1.1" 200 None (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:396)
2018-04-19 04:44:04.339 CEST
Starting new HTTPS connection (1): www.googleapis.com (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:824)
2018-04-19 04:44:04.802 CEST
https://www.googleapis.com:443 "POST /bigquery/v2/projects/<redacted>/jobs HTTP/1.1" 200 None (/base/data/home/apps/e~<redacted>/lib/urllib3/connectionpool.py:396)
2018-04-19 04:44:04.813 CEST
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
bigquerycron.py

from __future__ import absolute_import
from google.cloud import bigquery
import webapp2

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.write('CRON test page')          

def writeDataTest(dataset_id = '<redacted>',table_id='<redacted>'):
    client = bigquery.Client.from_service_account_json("credentials.json")
    job_config = bigquery.QueryJobConfig()
    table_ref = client.dataset(dataset_id).table(table_id)
    job_config.destination = table_ref
    job_config.write_disposition = 'WRITE_APPEND'

    query_job = client.query(
    """SELECT CURRENT_DATETIME() AS Datetime, 'CRON' as Source""", job_config=job_config)

writeDataTest()

app = webapp2.WSGIApplication([
      ('/bigquerycron', MainPage),
], debug=True)

我怀疑如果你删除app.yaml中的“login:admin”部分,它就会工作

如果这是问题所在,请确保您有适当的


这里有一些用于和的文档。

虽然我不确定原因,但我认为授权App engine的服务帐户不足以访问BigQuery

为了授权您的应用程序访问BigQuery,您可以使用以下两种方法之一:

  • 在app.yaml文件中,将指向服务帐户密钥文件的正确授权配置配置为BigQuery:

    环境变量: GOOGLE_应用程序_凭据=[YOURKEYFILE].json

  • 您的代码执行从bucket中提取授权服务帐户密钥的操作,然后在的帮助下加载该密钥。鉴于您的运行时是python,您应该使用以下代码:

    从google.cloud导入存储

    def下载密钥():

    “”“从存储桶中下载密钥。”“”

    storage\u client=storage.client()

    bucket=存储\客户端。获取\ bucket('您的bucket')

    blob=bucket.blob('keynameinbucket.json')

    blob.download_to_filename('Keynameinyourapp.json'))

    #在守则内:

    下载_key()

    client=bigquery.client.from\u service\u account\u json('keynameinyourapp.json'))


  • 在这种特定情况下,凭据不是问题,问题仅仅在于函数调用的位置,因为对App Engine的工作方式存在误解。bigquery的函数调用应该在MainPage类定义中移动,fixed bigquerycron.py如下所示(只移动了一行代码):

    来自未来导入绝对导入
    从google.cloud导入bigquery
    导入webapp2
    类主页(webapp2.RequestHandler):
    def get(自我):
    self.response.headers['Content-Type']='text/plain'
    self.response.write('CRON测试页')
    WriteDateTest()
    def WRITEDATEST(数据集\u id=“”,表\u id=“”):
    client=bigquery.client.from\u service\u account\u json(“credentials.json”)
    job_config=bigquery.QueryJobConfig()
    table\u ref=client.dataset(dataset\u id).table(table\u id)
    作业\配置.destination=表\参考
    job_config.write_disposition='write_APPEND'
    query\u job=client.query(
    “”“选择当前_DATETIME()作为日期时间,选择CRON作为源”“,job_config=job_config)
    app=webapp2.WSGIApplication([
    (“/bigquerycron”,主页),
    ],debug=True)
    
    OP中的Version实际上只向BigQuery写入一次,当第一次加载App Engine App时,所有后续调用都只执行MainPage类,在本例中,MainPage类什么也不做,因为实际的BigQuery代码在它之外

    此外,在不使用google cloud python库的情况下重写应用程序将是有益的,这在GAE标准()中不受支持。这尤其令人遗憾,因为即使是python的官方bigquery文档()使用此库。但是,有多种变通方法可以继续使用它,包括链接github问题中提到的一些方法,以及此处提到的方法: 本例中使用了类似的解决方法

    但如前所述,最好使用专用于Python的Google API客户端库:

    您是在计算引擎上运行此操作,还是每次要执行此操作时都要登录到云shell?这是作为部署了app engine的应用程序运行的,为了进行测试,我运行这些脚本(手动执行.py文件)通过cloud shell,我没有任何问题,但问题是何时使用自动cron作业进行调度。您是否尝试过在实例上使用Crontab而不是cron作业进行调度,只是为了消除这一潜在问题?此外,您可以显式地将.json客户机凭据添加到Python代码中以使用服务帐户想要使用cron作业,因为这只是我们想要用它实现的第一个用例。至于我以前从未使用过的凭据(真正的任何形式的身份验证),你能用一个例子修改我文章中的第一个bigquerycron.py以便我可以测试它吗?我使用
    client=bigquery.client.from_service_account_json(“my_file.json”)
    在我的自动Python脚本中,此文件位于实例的本地目录中。尝试在代码中使用此文件并添加.json凭据文件。它所做的只是打开url供任何人访问,管理员登录和cron作业都可以访问并触发页面。在应用程序引擎端执行代码不是问题而是当BigQuery
    from __future__ import absolute_import
    from google.cloud import bigquery
    import webapp2
    
    class MainPage(webapp2.RequestHandler):
        def get(self):
            self.response.headers['Content-Type'] = 'text/plain'
            self.response.write('CRON test page')          
    
    def writeDataTest(dataset_id = '<redacted>',table_id='<redacted>'):
        client = bigquery.Client.from_service_account_json("credentials.json")
        job_config = bigquery.QueryJobConfig()
        table_ref = client.dataset(dataset_id).table(table_id)
        job_config.destination = table_ref
        job_config.write_disposition = 'WRITE_APPEND'
    
        query_job = client.query(
        """SELECT CURRENT_DATETIME() AS Datetime, 'CRON' as Source""", job_config=job_config)
    
    writeDataTest()
    
    app = webapp2.WSGIApplication([
          ('/bigquerycron', MainPage),
    ], debug=True)
    
    cron:
    - url: /bigquerycron
      schedule: every 30 minutes
    
    from __future__ import absolute_import
    from google.cloud import bigquery
    import webapp2
    
    class MainPage(webapp2.RequestHandler):
        def get(self):
            self.response.headers['Content-Type'] = 'text/plain'
            self.response.write('CRON test page')          
            writeDataTest()
    
    def writeDataTest(dataset_id = '<redacted>',table_id='<redacted>'):
        client = bigquery.Client.from_service_account_json("credentials.json")
        job_config = bigquery.QueryJobConfig()
        table_ref = client.dataset(dataset_id).table(table_id)
        job_config.destination = table_ref
        job_config.write_disposition = 'WRITE_APPEND'
        query_job = client.query(
        """SELECT CURRENT_DATETIME() AS Datetime, 'CRON' as Source""", job_config=job_config)
    
    app = webapp2.WSGIApplication([
          ('/bigquerycron', MainPage),
    ], debug=True)