본문 바로가기

python & django & scipy

[pandas & django] gspread 사용하기

 

2022.12.23 - [python & django & pandas] - [pandas] google sheet 에서 데이터 가져오기

 

[pandas] google sheet 에서 데이터 가져오기

회사에서 google sheet 데이터를 받아온 후 그 데이터로 처리해야하는 일이 있었다. 인풋값으로 구글 시트를 다운 받은 엑셀파일을 하나하나 전달받아서 받아와야한다는 점이 불편해서 google sheet

darever.tistory.com

이전 글에 이어서

 

 

문제상황

데이터를 처리한 후 결과값을 엑셀 파일로 내보내야 했다.

input값으로 google sheet를 불러오는 것까지는 했는데, output 데이터를 어떤식으로 줘야하는지가 문제였다.

서버에서 돌려줘야하는 데이터는 input으로 불러온 데이터의 validation check 결과값과 현재 DB 데이터와의 비교 결과값이었다.

해당 결과값을 dataframe으로 돌려줘야하는 것은 명확하니 이제 excel 혹은 csv 파일로 return 해줘야하는데

꼭 파일로 return을 해줘야할까? 하는 의문점이 생겼다. 

서버로 request한 timestamp를 찍어서 새로운 google sheet를 만들어 email로 공유할까? 하다가 굳이 그럴 필요까지 없이 그냥 input으로 받았던 google sheet 데이터에 새로운 시트를 추가해서 매번 그 시트에 데이터를 덮어쓰면 되는 상황이라

dataframe 형식의 output값을 google sheet에 바로 적을 수 있는 방법이 있을 거라 생각하고 찾아봤더니 역시나 gspread를 사용하면 google sheet에 바로 데이터를 덮어씌울 수 있었다. 

 

 

해결

 

https://docs.gspread.org/en/v5.7.0/

 

gspread — gspread 5.7.0 documentation

© Copyright 2022, Anton Burnashev Revision d3df6d8b.

docs.gspread.org

 

 

 

google sheet api의 credential을 발급받는 부분은 아래 블로그를 참고했다. 

 

https://jellybeanz.medium.com/google-sheets-create-read-delete-guide-google-sheetss%EC%83%9D%EC%84%B1-%EC%9D%BD%EA%B8%B0-%EC%88%98%EC%A0%95-api-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95-5c9f243cecb3

 

Google Sheets Create/Read/Delete Guide : Google Sheetss생성/읽기/수정 API 사용 방법

프로젝트를 진행하다 보면 다른 사람들과 공유를 위해 Google Drive 를 이용하는 경우가 많다. 종종 Google Drive 에 작업한 결과를 업로드하여 관리하는 경우도 있는데, 일일이 사람이 업로드 하는 것

jellybeanz.medium.com

 

 

 

받아온 secret_key를 dict형태로 google_sheet_api_credential에 정의한 뒤,

gspread의 service_account_from_credential_from_dict 메소드를 통해 인증할 수 있다. 

import gspread

google_sheet_api_credentials = dict(
    type="service_account",
    project_id="f*********",
    private_key_id="43782f06e9e2*************",
    private_key="-----BEGIN PRIVATE KEY-----\nM7W6vT+1P********0FOzf/ex+HokxVGQ==\n-----END PRIVATE KEY-----\n",
    client_email="dare*****@******.iam.gserviceaccount.com",
    client_id="1124310*********",
    auth_uri="https://accounts.google.com/o/oauth2/auth",
    token_uri="https://oauth2.googleapis.com/token",
    auth_provider_x509_cert_url="https://www.googleapis.com/oauth2/v1/certs",
    client_x509_cert_url="https://www.googleapis.com/rob**********"
)
    
try:
    gc = gspread.service_account_from_dict(self.google_sheet_api_credentials)
except ValueError:
    raise self.GoogleSheetAPIError('google sheet api 인증 오류')

 

 

client_email로 공유된 google sheet는 아래처럼 불러와 사용할 수 있다.

create 메소드를 이용해 새로 만들어서 다른 사용자와 share 할 수도 있다.

 

처음에는 새로운 sheet를 만들어서 다른 사용자와 공유하려고 했는데 굳이 그럴 필요 없이 원래 구글 시트에 새로운 워크시트를 추가해도 됐기 때문에 굳이 create, share할 필요는 없없다.

 

gs = gc.open('sheet name')

worksheet는 google sheet 안의 sheet 이름을 가져오면 된다.

당연하지만 이 때 sheet1은 존재하는 워크시트여야만 한다. 

worksheet = gs.worksheet('sheet1')

원래 데이터가 있던 시트에 덮어쓰는 것이기 때문에 워크시트의 데이터를 지워주었다. 

worksheet.clear()

 

 

pandas DataFrame의 데이터를 구글시트에 덮어써야하기 때문에 gspread_dataframe 패키지를 사용했다. 

https://pypi.org/project/gspread-dataframe/

 

gspread-dataframe

Read/write gspread worksheets using pandas DataFrames

pypi.org

 

 

include_index, include_column_header, resize 등 여러 option을 사용해서 작성할 수 있다. 

import gspread_dataframe as gd

gd.set_with_dataframe(worksheet=worksheet, dataframe=df_result, include_index=False,
                              include_column_header=True, resize=True)

 

모든 로직이 완료되면 구글 시트에 데이터가 들어가있는 것을 확인할 수 있다. 

 

 

 

전체 코드

import pandas as pd
import gspread
import gspread_dataframe as gd

google_sheet_api_credentials = dict(
    type="service_account",
    project_id="f*********",
    private_key_id="43782f06e9e2*************",
    private_key="-----BEGIN PRIVATE KEY-----\nM7W6vT+1P********0FOzf/ex+HokxVGQ==\n-----END PRIVATE KEY-----\n",
    client_email="dare*****@******.iam.gserviceaccount.com",
    client_id="1124310*********",
    auth_uri="https://accounts.google.com/o/oauth2/auth",
    token_uri="https://oauth2.googleapis.com/token",
    auth_provider_x509_cert_url="https://www.googleapis.com/oauth2/v1/certs",
    client_x509_cert_url="https://www.googleapis.com/rob**********"
)

df_result = pd.DataFrame(...) # 구글 시트에 작성할 데이터


# google sheet api 인증
try:
    gc = gspread.service_account_from_dict(self.google_sheet_api_credentials)
except ValueError:
    raise Exception('google sheet api 인증 오류')

# google sheet 열기
try:
	gs = gc.open('my data')
except ValueError:
	raise Excpetion('구글 시트를 찾을 수 없음')

# worksheet 열기
try:
	worksheet = gs.worksheet('sheet1')
except Exception as sheet_name:
	raise Exception(f'{sheet_name} 워크시트를 찾을 수 없음')

worksheet.clear()

# dataframe 데이터 worksheet에 작성하기
gd.set_with_dataframe(worksheet=worksheet, dataframe=df_result, include_index=False,
                              include_column_header=True, resize=True)

 

 

결론

구글 시트에 바로 적용할 수 있다는 건 좋지만 상당히 느려서(sheet 두개에 쓰는데 평균 6~7초 정도 걸림) 상용 서비스에는 사용하기 어려울 것 같다. request가 잦지 않은 어드민 시스템에서는 사용할만해서 사용하기로 결정했다.