Загрузка Google Sheet в формате CSV с помощью Python дает CSV, который состоит всего из одной строки

#python #google-api #google-drive-api #google-sheets-api #google-api-python-client

Вопрос:

Я создал довольно простую программу, которая берет лист Google и преобразует его в файл CSV, а затем выплевывает указанный CSV в заданный каталог. Эта часть работает так, как задумывалось, но результат .CSV не имеет разрывов строк или новых строк, поэтому, когда он загружается в Excel, он читается как одна строка, rn вместо новых строк.

В этой программе есть некоторые ненужные импортные и другие проблемы, но я просто еще не очистил их.

Вот программа:

 # Package Imports
from __future__ import print_function
import re
import os.path
import io
import csv
import ctypes
import google.auth.exceptions
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from googleapiclient.http import MediaIoBaseDownload

# Function Runners (for test purposes)

# Other Programmable Strings
EXPORT_DIRECTORY = 'DIREC'
CREDS_DIRECTORY = 'DIREC'
GSHEET_ID = 'ID'
FILE_NAME = 'NAME'   '.csv'
# When editing this URL, token.json MUST be deleted to reauthorize with Google.
SCOPES = 'https://www.googleapis.com/auth/drive'

# Define Global Variables
MessageBox = ctypes.windll.user32.MessageBoxW

def main():
    creds = None

    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)

    # If there are no (valid) credentials available, directs user to OAuth login through default browser.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            try:
            
                creds.refresh(Request())

            except google.auth.exceptions.RefreshError:
                MessageBox(None, 'There was an error authorizing with Google. You will be redirected to a login page.', 'Google Sheet to CSV: Fatal Error', 0)

        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'C:\UsersAeroGOneDriveDesktopSHEETSCSVcredentials.json', SCOPES) # Sometimes requires a specific path to credentials.json.
            creds = flow.run_local_server(port=0)

        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    service = build('drive', 'v3', credentials=creds)
 

В основном все, что вам нужно посмотреть, — это эта часть ниже.

     # Call the Drive v3 API and compile CSV file from provided ID
    file_id = GSHEET_ID
    request = service.files().export_media(fileId=file_id,
                                             mimeType='text/csv')
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print("Download %d%%." % int(status.progress() * 100))
    
    fh.seek(0)
    with open('C:\UsersAeroGOneDriveDesktopSHEETSCSV\'   FILE_NAME, 'w', newline='rn') as f:
        f.write(str(fh.read()))
        f.close()

if __name__ == '__main__':
    main()
 

Мне действительно нужна помощь здесь. В двух словах, то, что происходит, — это выходной CSV, который я получаю, это:

b’ ,Jurisdiction,SHIPPING_ID,Combined,JobTitle,Shipping_Address,City,State,Zip,Phone,Email,Bill to addresses,,JobTitle,Address,City,State,Zip,Phone,EmailrnDATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,,,,,,,,,rnDATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,,,,,,,,,rnDATA,DATA,DATA,DATA

вместо желаемого результата, который заключается в следующем:

b’ ,Jurisdiction,SHIPPING_ID,Combined,JobTitle,Shipping_Address,City,State,Zip,Phone,Email,Bill to addresses,,JobTitle,Address,City,State,Zip,Phone,Email DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,,,,,,,,, DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,DATA,,,,,,,,, DATA,DATA,DATA,DATA

Я понимаю rn , что предполагается перевести на новую строку, но это не так. Я очень признателен за любую помощь или что-то, что поможет мне направить меня в правильном направлении. Я не против любого решения, даже если оно включает в себя какой-то обходной метод.

Ответ №1:

Это пример из документации. Я задаюсь вопросом, не связана ли проблема с тем, как вы записываете кусочки в файл.

 file_id = '1ZdR3L3qP4Bkq8noWLJHSr_iBau0DNT4Kli4SxNc2YEo'
request = drive_service.files().export_media(fileId=file_id,
                                             mimeType='application/pdf')
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
    status, done = downloader.next_chunk()
    print "Download %d%%." % int(status.progress() * 100)
 

Почему бы не пойти немного проще?

 with open('C:\UsersAeroGOneDriveDesktopSHEETSCSV\'   FILE_NAME, "wb") as f:
    f.write(fh.getbuffer())
 

Комментарии:

1. Я ожидал, что проблема была в том, как байты записывались в файл, я просто понятия не имел, куда идти. Ваш подход сработал как заклинание. Большое вам спасибо, вы упростили код и исправили проблему, вы лучший.