DEV Community

Cover image for Setting up Python to Connect to Google Sheets
Rose Day
Rose Day

Posted on • Updated on

Setting up Python to Connect to Google Sheets

Happy Thursday! I hope you are all doing well. It has been exciting to continue working with Twilio and Google sheets on this project. This week I will focus on the issues and learnings I had with using Google's APIs for the first time.

Quick Recap

At the moment, I spend time logging migraines for the doctors office but don't remember the format she wanted, or the details she found important. This application is being created as a way to request a survey for a migraine through SMS, quickly fill out the details, and log the data for later use at the doctors appointment.

Link to Code

To clone or view the code, please visit my GitHub project here. This project is a current work in progress and is not fully functional at this time.

Issues and Learnings

API Errors due to Scope

The first issue I ran into when trying to implement code to interact with Google Sheets through API was related to scope issues. I first assumed I had setup the configuration file wrong but later realized it was due to version changes on the API and referencing older tutorials. The issue I was seeing was as follows:

gspread.exceptions.APIError: {'errors': [{'domain': 'global', 'reason': 'insufficientPermissions', 'message': 'Insufficient Permission: Request had insufficient authentication scopes.'}], 'code': 403, 'message': 'Insufficient Permission: Request had insufficient authentication scopes.'}
Enter fullscreen mode Exit fullscreen mode

After spending time researching this error, I came across a post that showed the scopes needed were the two shown below:

# Create a spread client authorizing it using those credentials.
scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
Enter fullscreen mode Exit fullscreen mode

What did I learn here? The reason this issue was occurring was due to an API update. gspread was upgraded and is based on API v4. The change allowed the API to be faster than previous versions but also required scopes to be updated in order to work properly.


Path Issues with PyTest

The next issue I ran across was when working with PyTest. The constructor of the class I setup to work with spreadsheets requires two inputs (1) filename of the JSON containing the credentials for the API which includes the path in the input, and (2) the name of the sheet to connect to.

When working with this constructor in the executor.py file, I provided the path seen below, which worked as expected. (Note: This code will later move to the app.py file when the Twilio API is introduced.)

sheet1 = spreadsheet('../client_secret.json', "migraine_tracker")
Enter fullscreen mode Exit fullscreen mode

Utilizing the same line, I placed the code into a test file and came back with the warning WARNING: Failed to generate report: No data to report. meaning that no data could be read.

After seeing this, I installed pytest-cov to analyze the test coverage and see what lines were being hit and what lines were being missed. At this point, I realized the test coverage was stopping at an important line in the constructor:

credentials = ServiceAccountCredentials.from_json_keyfile_name(json, scope)
Enter fullscreen mode Exit fullscreen mode

Therefore, the credentials were not being created due to this line failing and the sheet was not able to be called.

When looking back at the test for the line that provides the JSON file, I worked to determine why the path was not working correctly. To look further at the path issue, I created a small test that would assert if the path existed. I ran this test with both paths ../client_secret.json and client_secret.json, at which point I found out the path needed to be the latter to work properly in the test file.

import os.path
import pytest
import pprint

def test_path():
    """
    Determine if the path specified is correct.
    """
    assert path.exists('client_secret.json') # Produces True and pass 
    assert path.exists('../client_secret.json') # Produces False and fail 
Enter fullscreen mode Exit fullscreen mode

Therefore, I changed the input into the constructor which in turn fixed my issue and made it so I could run my tests successfully.

sheet1 = spreadsheet('client_secret.json', "migraine_tracker")
Enter fullscreen mode Exit fullscreen mode

What did I learn here? Check the root directory. Pytest was running from rootdir: /../../../twilio_application and not the folder I was expecting it to run from. Seems like a trivial mistake when looking back at it, but it is something that can easily be overlooked.


Development Stack

So far, I have worked on the code needed to interact with Google Sheets API...

Alt Text

Stay tuned for next weeks post where I discuss how I utilize the Twilio API to develop a Python Flask app that generates a survey for migraines. I look forward to sharing with you the issues and learnings I have encountered while learning to use Flask!

Additional Resources

Reference Links

Google Sheets and Python Example
Accessing Google Spreadsheets with Python
Python Check if File or Directory Exists
pytest
pytest-cov

Top comments (2)

Collapse
 
lizziepika profile image
Lizzie Siegle

Love this idea! Very useful and relevant.

Collapse
 
rosejcday profile image
Rose Day

Thank you, glad to hear! 😄