2

入力としてcsvを受け取り、それを単一のスプレッドシートドキュメントに書き込む簡単なスクリプトを作成しようとしています。今は動作していますが、スクリプトは遅いです。2 つのワークシートに cca 350 行を書き込むのに約 10 分かかります。

これが私が持っているスクリプトです:

#!/usr/bin/python
import json, sys
import gspread
from oauth2client.client import SignedJwtAssertionCredentials

json_key = json.load(open('client_secrets.json'))
scope = ['https://spreadsheets.google.com/feeds']

# change to True to see Debug messages
DEBUG = False

def updateSheet(csv,sheet):
    linelen = 0
    counter1 = 1 # starting column in spreadsheet: A
    counter2 = 1 # starting row in spreadsheet: 1
    counter3 = 0 # helper for iterating through line entries
    credentials = SignedJwtAssertionCredentials(json_key['client_email'], json_key['private_key'], scope)

    gc = gspread.authorize(credentials)

    wks = gc.open("Test Spreadsheet")
    worksheet = wks.get_worksheet(sheet)
    if worksheet is None:
        if sheet == 0:
            worksheet = wks.add_worksheet("First Sheet",1,8)
        elif sheet == 1:
            worksheet = wks.add_worksheet("Second Sheet",1,8)
        else:
            print "Error: spreadsheet does not exist"
            sys.exit(1)

    worksheet.resize(1,8)

    for i in csv:
        line = i.split(",")
        linelen = len(line)-1
        if (counter3 > linelen):
            counter3 = 0
        if (counter1 > linelen):
            counter1 = 1

        if (DEBUG):
            print "entry length (starting from 0): ", linelen
            print "line: ",  line
            print "counter1: ", counter1
            print "counter3: ", counter3
        while (counter3<=linelen):
            if (DEBUG):
                print "writing line: ", line[counter3]
            worksheet.update_cell(counter2, counter1, line[counter3].rstrip('\n'))
            counter3 += 1
            counter1 += 1

        counter2 += 1
        worksheet.resize(counter2,8)

私はシステム管理者なので、くだらないコードについて事前に謝罪します。

とにかく、スクリプトはcsvから1行ずつ取得し、カンマで分割し、セルごとに書き込むため、書き込むのに時間がかかります。これを cron に 1 日に 1 回実行させ、古いエントリを削除して新しいエントリを書き込むという考え方です。これが resize() を使用する理由です。

今、私は今のようにセルごとに書き込むのを避けて、csv行全体を取り、それを独自のセルに各値を入れてシートに書き込むより良い方法があるかどうか疑問に思っていますか? これにより、実行にかかる時間が大幅に短縮されます。

ありがとう!

4

1 に答える 1

3

はい、これは可能です。私は100行×12行のチャンクでアップロードし、それをうまく処理します.csv全体のようなものに対して、これがどれだけうまくスケーリングされるかはわかりません. また、シートのデフォルトの長さは 1000 行であり、この範囲外の行を参照しようとするとエラーが発生することに注意してください (add_rows事前にスペースを確保するために使用してください)。簡単な例:

data_to_upload = [[1, 2], [3, 4]]

column_names = ['','A','B','C','D','E','F','G','H', 'I','J','K','L','M','N',
                'O','P','Q','R','S','T','U','V','W','X','Y','Z', 'AA']

# To make it dynamic, assuming that all rows contain same number of elements
cell_range = 'A1:' + str(column_names[len(data_to_upload[0])]) + str(len(data_to_upload)) 

cells = worksheet.range(cell_range)

# Flatten the nested list. 'Cells' will not by default accept xy indexing.
flattened_data = flatten(data_to_upload)

# Go based on the length of flattened_data, not cells. 
# This is because if you chunk large data into blocks, all excess cells will take an empty value
# Doing the other way around will get an index out of range
for x in range(len(flattened_data)):
    cells[x].value = flattened_data[x].decode('utf-8')

worksheet.update_cells(cells)

cells行の長さが異なる場合は、2 つのリストが同期されないように、適切な数の空の文字列を挿入する必要があることは明らかです。特殊文字でクラッシュし続けたので、便宜上デコードを使用しているので、それを入れるのが最善のようです.

于 2016-01-17T10:04:46.297 に答える