2014-12-09 3 views
1

Я пытаюсь получить содержимое моей базы данных sqlite3 и обновлять эти данные, используя скребок в цикле for.Пакет Python Dataset package & looping/update rows -

Предполагаемая поток выглядит следующим образом:

  • Получить все строки из набора данных
  • Для каждой строки, найти столбец URL и принести некоторые дополнительные (обновлено) Данные
  • После того, как эти данные были получены, upsert (обновить, добавить столбцы, если не существует), эти данные в строку, из которой был взят URL.
  • Мне нравится пакет набора данных из-за «upsert», позволяя ему динамически добавлять любые столбцы, которые я, возможно, добавил в базу данных, если они не существуют.

    Мой код выдает ошибку, которую я не могу объяснить.

    'ResourceClosedError: This result object is closed.' 
    

    Как я могу получить свою цель, не столкнувсь с этим? Следующий фрагмент воссоздает мою проблему.

    импорт набор данные дб = dataset.connect («SQLite: ///test.db»)

    # Add two dummy rows 
    testrow1 = {'TestID': 1} 
    testrow2 = {'TestID': 2} 
    db['test'].upsert(testrow1, ['TestID']) 
    db['test'].upsert(testrow2, ['TestID']) 
    print("Inserted testdata before loop") 
    
    # This works fine 
    testdata = db['test'].all() 
    for row in testdata: 
        print row 
    # This gives me an 'ResourceClosedError: This result object is closed.' error? 
    i = 1 # 'i' here exemplifies data that I'll add through my scraper. 
    testdata = db['test'].all() 
    for row in testdata: 
        data = {'TestID': i+1000} 
        db['test'].upsert(data, ['TestID']) 
        print("Upserted within loop (i = " + str(i) + ")") 
        i += 1 
    

    ответ

    2

    Проблема может быть, вы запрашиваете набор данных и доступ к объекту результата (под «это работает fine ") и все это считывается в цикле, а затем сразу же пытается повторить еще один цикл с upserts на одном и том же объекте результата. Ошибка сообщает вам, что ресурс был закрыт, в основном, как только вы его прочитаете, соединение закрывается автоматически (как функция!). (see this answer о «автоматическом закрытии» для более подробного объяснения причин и способов обойти его.)

    Учитывая, что результирующие ресурсы, как правило, закрываются, попробуйте запросить результаты снова в начале вашего цикла upsert:

    i = 1 # 'i' here exemplifies data that I'll add through my scraper. 
    testdata = db['test'].all() 
    for row in testdata: 
        data = {'TestID': i} 
        db['test'].upsert(data, ['TestID']) 
        print("Upserted within loop (i = " + str(i) + ")") 
        i += 1 
    

    Edit: Смотрите комментарий, приведенный выше код изменит Testdata внутри цикла и, таким образом, все еще дает ту же ошибку, поэтому способ обойти это - сначала прочитать данные в массиве, а затем пропустить этот массив для выполнения обновлений. Что-то вроде:

    i = 1 # 'i' here exemplifies data that I'll add through my scraper. 
    testdata = [row for row in db['test'].all()] 
    for row in testdata: 
        data = {'TestID': i} 
        db['test'].upsert(data, ['TestID']) 
        print("Upserted within loop (i = " + str(i) + ")") 
        i += 1 
    
    +0

    Спасибо! Ты определенно прав на тех первых ошибках ;-) Я отредактировал вопрос. Ваше решение, похоже, не избавляется от этой ошибки, хотя я нашел обходное решение, выбрав элементы в списке до цикла - кажется, что это не похоже на цикл над ним при обновлении одной и той же таблицы? – MattV

    +0

    Это действительно имеет смысл, потому что вы меняете то, что вы зацикливаете внутри цикла, что может привести к непредсказуемым результатам, если это разрешено. Я отредактировал мой ответ, спасибо за upvote! – brobas

    Смежные вопросы