Unrecognized arguments using oauth2 and Google API

2019-02-24 07:14发布

I'm using the Google API services in some scripts and having some problems. This error is something weird, but here we go. I have a script that is listing my Google Drive files.

from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools

SCOPES = 'https://www.googleapis.com/auth/drive.readonly.metadata'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)
DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http()))

files = DRIVE.files().list().execute().get('files', [])
for f in files:
    print(f['name'], f['mimeType'],f['id'])

It works perfectly, I download the client_secret.json from Google API and save it in the same folder, then I start the script to check everythings is ok.

Then I start to edit my file to change the way how I execute it and don't read a file, instead, call the script and send the client_id and client_secret strings to the script, and the final version is this:

import sys
from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools

# ID and SECRET arguments
client_id = sys.argv[1]
client_secret = sys.argv[2]

SCOPES = 'https://www.googleapis.com/auth/drive.readonly.metadata'

def listFiles(drive):
    """Receive the service and list the files"""
    files = drive.files().list().execute().get('files', [])
    for f in files:
        print(f['name'], f['mimeType'],f['id'])

def main():
    store = file.Storage('storage.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.OAuth2WebServerFlow(client_id, client_secret, SCOPES)
        creds = tools.run_flow(flow, store, tools.argparser.parse_args())
    DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http()))
    listFiles(DRIVE)


if __name__ == "__main__":
    main()

The first time that I start this new version of the script it works, because the script in the old version has created the storage.json file. Then I move my new version script to another folder or machine (where the storage.json file doesn't exists) to check if it works and then I get this:

$ python3 drive_list.py asdasdasdsa jijfkljflksdjflksdj

/usr/local/lib/python3.4/dist-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access storage.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))
usage: drive_list.py [--auth_host_name AUTH_HOST_NAME]
                     [--noauth_local_webserver]
                     [--auth_host_port [AUTH_HOST_PORT [AUTH_HOST_PORT ...]]]
                     [--logging_level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
drive_list.py: error: unrecognized arguments: asdasdasdsa jijfkljflksdjflksdj

The warning about the storage.json file is normal and appears in both script versions, is part of oauth2client.

This is the curios part, why the arguments are recognized when the storage.json file exists (ONLY created reading the client_secret.json)? if the first time that the script start it creates the file. Is really weird this error, and I'm just trying to find what is happening exactly. If someone can help me, I will be really thankful.

1条回答
疯言疯语
2楼-- · 2019-02-24 08:10

This is happening because you are importing the oauth2client.tools module.

To work correctly this module relies on the standard argparse module. In case you don't know, this standard module is used to write user-friendly command-line interfaces with easy management of command line arguments. This does not get along with your usage of sys.argv[1] and sys.argv[2] arguments.

To work around this, you can add new arguments to the command line like in the sample below. With this modification you would then run the tool like this

python3 drive_list.py -ci "your_client_id" -cs "your_client_secret"

Here is your code slightly modified to add the new command line arguments:

import argparse
from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools

# ID and SECRET arguments as new command line parameters
# Here is where you extend the oauth2client.tools startnd arguments
tools.argparser.add_argument('-ci', '--client-id', type=str, required=True, help='The client ID of your GCP project')
tools.argparser.add_argument('-cs', '--client-secret', type=str, required=True,
                             help='The client Secret of your GCP project')

SCOPES = 'https://www.googleapis.com/auth/drive.readonly.metadata'


def list_files(drive):
    """Receive the service and list the files"""
    files = drive.files().list().execute().get('files', [])
    for f in files:
        print(f['name'], f['mimeType'], f['id'])


def main():
    store = file.Storage('storage.json')
    creds = store.get()
    if not creds or creds.invalid:
        # You want to be sure to parse the args to take in consideration the new parameters
        args = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
        flow = client.OAuth2WebServerFlow(args.client_id, args.client_secret, SCOPES)
        creds = tools.run_flow(flow, store, tools.argparser.parse_args())
    drive_sdk = discovery.build('drive', 'v3', http=creds.authorize(Http()))
    list_files(drive_sdk)


if __name__ == "__main__":
    main()
查看更多
登录 后发表回答