Подтвердить что ты не робот

Cursor.fetchall() vs list (курсор) в Python

Оба метода возвращают список возвращенных элементов запроса, я что-то здесь упустил?
Или они действительно имеют идентичные использования?
Есть ли различия в производительности?

4b9b3361

Ответ 1

Если вы используете курсор по умолчанию, MySQLdb.cursors.Cursor, весь результирующий набор будет сохранен на стороне клиента (т.е. в списке Python) к моменту завершения cursor.execute().

Поэтому, даже если вы используете

for row in cursor:

у вас не будет уменьшения объема памяти. Весь набор результатов уже сохранен в списке (см. self._rows в MySQLdb/cursors.py).

Однако, если вы используете SSCursor или SSDictCursor:

import MySQLdb
import MySQLdb.cursors as cursors

conn = MySQLdb.connect(..., cursorclass=cursors.SSCursor)

тогда набор результатов хранится на сервере mysqld. Теперь вы можете написать

cursor = conn.cursor()
cursor.execute('SELECT * FROM HUGETABLE')
for row in cursor:
    print(row)

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

В противном случае, как уже указывали другие, cursor.fetchall() и list(cursor) по существу совпадают.

Ответ 2

cursor.fetchall() и list(cursor) по существу одинаковы. Другой вариант состоит в том, чтобы не извлекать список, а вместо этого просто перебирать объект с открытым курсором:

for result in cursor:

Это может быть более эффективным, если результирующий набор является большим, так как ему не нужно извлекать весь набор результатов и хранить все в памяти; он может просто увеличивать каждый элемент (или партии их меньшими партиями).

Ответ 3

Значение A (с учетом MySQLdb/PyMySQL), которое стоит отметить при использовании DictCursor, заключается в том, что list(cursor) всегда будет предоставлять вам список, а cursor.fetchall() предоставляет вам список, если результирующий набор пуст, и в этом случае это дает вам пустой кортеж. Это было в MySQLdb и остается в случае нового PyMySQL, где не будет исправлено для соображений обратной совместимости. Хотя это не является нарушением спецификации API Python Database, это все еще удивительно и может легко привести к ошибке типа, вызванной ошибочным допущением, что результат это список, а не просто последовательность.

Учитывая вышеизложенное, я предлагаю всегда одобрять list(cursor) над cursor.fetchall(), чтобы избежать попадания в таинственный тип ошибки в случае края, где ваш результирующий набор пуст.

Ответ 4

list(cursor) работает, потому что курсор является итерируемым; вы также можете использовать cursor в цикле:

for row in cursor:
    # ...

Хорошая реализация адаптера базы данных будет извлекать строки в пакетах с сервера, сохраняя требуемый объем памяти, поскольку ему не нужно удерживать полный набор результатов в памяти. cursor.fetchall() должен вернуть полный список.

Нет смысла использовать list(cursor) над cursor.fetchall(); конечный эффект тогда действительно тот же самый, но вы теряли возможность использовать результаты вместо этого.

Ответ 5

Вы можете использовать списки, чтобы поместить элемент из вашего кортежа в список:

conn = mysql.connector.connect()
cursor = conn.cursor()
sql = "SELECT column_name FROM db.table_name;"
cursor.execute(sql)

results = cursor.fetchall()
# bring the first item of the tuple in your results here
item_0_in_result = [_[0] for _ in results]