Quantcast
Channel: Planet Python
Viewing all articles
Browse latest Browse all 22462

Wesley Chun: Migrating from tools.run() to tools.run_flow()

$
0
0
This mini-tutorial slash migration guide slash PSA (public service announcement) is aimed at Python developers using the Google APIs Client Library (to access Google APIs from their applications) currently calling oauth2client.tools.run() and likely getting an exception (see Jan 2016 update below), and/or considering a migration to oauth2client.tools.run_flow(), its replacement. 

UPDATE (Jun 2016): Revised the code and cleaned up the dialog so there are no longer any instances of using run() function, significantly shortening this post.

UPDATE (Jan 2016): The tools.run() function itself was forcibly removed (without a fallback) in Aug 2015, so if you're using any release on or after that, any such calls from your code will throw an exception (AttributeError: 'module' object has no attribute 'run'). To fix this problem, continue reading.

Prelude

We're going to continue our look at accessing Google APIs from Python. In addition to the previous pair of posts (http://goo.gl/57Gufk and http://goo.gl/cdm3kZ), as part of my day job, I've been working on corresponding video content which is part of a developer series called the Launchpad Online. The goal of the series is to help introduce or "launch" developers into using Google APIs, dev tools, or specific API features.

The Google Developers Startups team runs the Launchpad bootcamp events featuring this content delivered live to help entrepreneurs get their startup companies off the ground! Specifically tied to these blogposts, check out episodes 2 (Creating new apps using Google APIs) and 3 (Accessing Google APIs: common code walkthrough).

Here in this follow-up, we're going to specifically address the sidebar in the previous post, where we bookmarked an item for future discussion where the future is now: in the oauth2client package, tools.run() has been deprecated by tools.run_flow(). We'll look at it now, but you need at least Python 2.7 (and 3.3) because it uses the argparse module, added in 2.7 and 3.2, but the Google APIs Client Library doesn't support any 3.x older than 3.3. If you didn't even know Python 3 was supported at all, then you need to see this post and this Quora Q&A.)

Command-line argument processing, or "Why argparse?"

Python has had several modules in the Standard Library that allow developers to process command-line arguments. The original one was getopt which mirrored the getopt() function from C. In Python 2.3, optparse was introduced, featuring more powerful processing capabilities. However, it was deprecated in 2.7 in favor of a similar module, argparse. (To find out more about their similarities, differences and rationale behind developing argparse , see PEP 389 and this argparse docs page.) For the purposes of using Google APIs, you're all set if using Python 2.7 as it's included in the Standard Library. Otherwise Python 2.3-2.6 users can install it with: "pip install -U argparse". 

Replacing tools.run() with tools.run_flow()

Now let's convert the authorized access to Google APIs code from using tools.run() to tools.run_flow(). Here is the old snippet I'm talking about that needs upgrading:
from apiclient import discovery
from httplib2 import Http
from oauth2client import file, client, tools

SCOPES = # one or more scopes (str or iterable)
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, store)

SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
The update involves adding lines that import argparse and using it to get the flags argument needed by tools.run_flow() plus the actual change from tools.run():
import argparse

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

SCOPES = # one or more scopes (str or iterable)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
creds = tools.run_flow(flow, store, flags)

SERVICE = discovery.build(API, VERSION, http=creds.authorize(Http()))
Just a few lines of code to change. Once you migrate to this new snippet with tools.run_flow(), your application should go back to working the way it had before.

Viewing all articles
Browse latest Browse all 22462

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>