4

I'm coding a scraper that uses gspread to read and write In Google Sheets.

In the "writting" part of the code I had to add a try-except because of an APIError caused by the quota limit of writting, so when the except Is executed It have wait 100 seconds and then continue. The problem is that It ignores the item that caused the except, but It was supposed to repeat that Item

    def process_cpf_list(self):

        # SKIP OVER COLUMN HEADING IN THE SPREADSHEET
        cpfs = self.sheet.col_values(self.cpf_col)[1:]
        bot_url = BOT()

        for row, cpf in enumerate(cpfs):
            nome, idade, beneficio, concessao, salario, bancos, bancocard, consig, card = bot_url.search_cpfs(cpf)

            # UPDATE THE SHEET
            print("Atualizando...")
            try:
                row = row + 2
                self.sheet.update_cell(row, self.nome_col, nome)
                self.sheet.update_cell(row, self.age_col, idade)
                self.sheet.update_cell(row, self.beneficio_col, beneficio)
                self.sheet.update_cell(row, self.concessao_col, concessao)
                self.sheet.update_cell(row, self.salario_col, salario)
                self.sheet.update_cell(row, self.bancos_col, bancos)
                self.sheet.update_cell(row, self.bancocard_col, bancocard)
                self.sheet.update_cell(row, self.consig_col, consig)
                self.sheet.update_cell(row, self.card_col, card)
                print('Cliente atualizado!')
            except APIError:
                print('Esperando para atualizar...')
                time.sleep(100)
                continue


cpf_updater = CpfSearch('TESTE')
cpf_updater.process_cpf_list()
Moises Felipe
  • 83
  • 2
  • 9

5 Answers5

3
while True:
    try:
        # do some stuff
        break # we didn't hit the exception, exit the loop
    except APIError:
        # handle the exception...
oittaa
  • 599
  • 3
  • 16
2

It shouldn't repeat the item in this case. When you iterate with for loop, once the item is picked, it won't be picked again.

You can add a while loop that will try infinitely to update unless the update succeeded:

for row, cpf in enumerate(cpfs):
    nome, idade, beneficio, concessao, salario, bancos, bancocard, consig, card = bot_url.search_cpfs(cpf)

    # UPDATE THE SHEET
    print("Atualizando...")
    max_retries = 3
    row = row + 2
    while max_retries:
        try:
            self.sheet.update_cell(row, self.nome_col, nome)
            self.sheet.update_cell(row, self.age_col, idade)
            self.sheet.update_cell(row, self.beneficio_col, beneficio)
            self.sheet.update_cell(row, self.concessao_col, concessao)
            self.sheet.update_cell(row, self.salario_col, salario)
            self.sheet.update_cell(row, self.bancos_col, bancos)
            self.sheet.update_cell(row, self.bancocard_col, bancocard)
            self.sheet.update_cell(row, self.consig_col, consig)
            self.sheet.update_cell(row, self.card_col, card)
            print('Cliente atualizado!')
            break
        except APIError:
            max_retries -= 1
            print('Esperando para atualizar...')
            time.sleep(100)

EDIT:

I have added a simple retries mechanism, which will try 3 times before it skips the row.

Gabio
  • 9,126
  • 3
  • 12
  • 32
  • Thanks for your help Gabip! I kinda worked, now when the code gets the `except APIError` It's waiting the time and them retrying. But them. It's writting on the wrong row of the sheet... I'v done some tests and found that the number of rows jumped when writting is the number of `max_retries` – Moises Felipe Apr 14 '20 at 18:53
  • Oh, I guess it's because the row incrementation is inside the while loop. I've updated the solution, could you try again? – Gabio Apr 14 '20 at 19:00
  • Happy to help :) – Gabio Apr 14 '20 at 20:46
0

You could put the content from Try: to a separate function. if that function throws an error it will be automatically catch in your except: block. there you can recall the said function.

Jaws
  • 497
  • 8
  • 22
0

why don't you just use a while-loop?

for row, cpf in enumerate(cpfs):
    nome, idade, beneficio, concessao, salario, bancos, bancocard, consig, card = bot_url.search_cpfs(cpf)

    # UPDATE THE SHEET
    print("Atualizando...")
    while True:
        try:
            row = row + 2
            self.sheet.update_cell(row, self.nome_col, nome)
            self.sheet.update_cell(row, self.age_col, idade)
            self.sheet.update_cell(row, self.beneficio_col, beneficio)
            self.sheet.update_cell(row, self.concessao_col, concessao)
            self.sheet.update_cell(row, self.salario_col, salario)
            self.sheet.update_cell(row, self.bancos_col, bancos)
            self.sheet.update_cell(row, self.bancocard_col, bancocard)
            self.sheet.update_cell(row, self.consig_col, consig)
            self.sheet.update_cell(row, self.card_col, card)
            print('Cliente atualizado!')
            break
        except APIError:
            print('Esperando para atualizar...')
            time.sleep(100)
Lukas
  • 381
  • 3
  • 13
0

Another option is to use the retrying library which handles retrys for you at the method level.

A benefit here is getting access to a lot of tested functionality like exponential back-offs/retrying N times only etc... without having to write it yourself.
A drawback is that you are adding a new dependency, if you're in a situation where that matters. And it might be more than you need - in which case using a while block and just retrying forever is much simpler.

For example, you would move your logic that is unreliable to a seperate method, and wrap it in a @retry annotation like so:

from retrying import retry

def process_cpf_list(self):

    ...

    for row, cpf in enumerate(cpfs):
        update_cells(...)


@retry(wait_fixed=100000)  # Retry after 100 seconds
def update_cells(...):
  self.sheet.update_cell(row, self.nome_col, nome) 
  etc...


cpf_updater = CpfSearch('TESTE')
cpf_updater.process_cpf_list()
Jethro
  • 3,029
  • 3
  • 27
  • 56