Заполнение базы данных SQLite3 из TXT файла с помощью Python
Я пытаюсь настроить веб-сайт в django, который позволяет пользователю отправлять запросы в базу данных, содержащую информацию об их представителях в Европейском парламенте. У меня есть данные в разделенном запятыми файле .txt со следующим форматом:
Парламент, имя, страна, партия_группа, национальная_партия, должность
7, Марта Андреасен, Соединенное Королевство, Европа группы свободы и демократии, Партия Независимости Соединенного Королевства, Член
и т.д....
Я хочу заполнить базу данных SQLite3 этими данными, но до сих пор все обучающие материалы, которые я нашел, показывают только, как это сделать вручную. Поскольку у меня есть 736 наблюдений в файле, я действительно не хочу этого делать.
Я подозреваю, что это просто, но я был бы очень признателен, если бы кто-нибудь мог показать мне, как это сделать.
Томас
Ответы
Ответ 1
Итак, если ваш models.py
выглядит примерно так:
class Representative(models.Model):
parliament = models.CharField(max_length=128)
name = models.CharField(max_length=128)
country = models.CharField(max_length=128)
party_group = models.CharField(max_length=128)
national_party = models.CharField(max_length=128)
position = models.CharField(max_length=128)
Затем вы можете запустить python manage.py shell
и выполнить следующее:
import csv
from your_app.models import Representative
# If you're using different field names, change this list accordingly.
# The order must also match the column order in the CSV file.
fields = ['parliament', 'name', 'country', 'party_group', 'national_party', 'position']
for row in csv.reader(open('your_file.csv')):
Representative.objects.create(**dict(zip(fields, row)))
И все готово.
Добавление (изменить)
По запросу Томаса объясните, что делает **dict(zip(fields,row))
:
Итак, fields
содержит список имен полей, которые мы определили, а row
содержит список значений, представляющих текущую строку в файле CSV.
fields = ['parliament', 'name', 'country', ...]
row = ['7', 'Marta Andreasen', 'United Kingdom', ...]
Что делает zip()
, он объединяет два списка в один список пар элементов из обоих списков (например, на молнии); т.е. zip(['a','b,'c'], ['A','B','C'])
вернет [('a','A'), ('b','B'), ('c','C')]
. Итак, в нашем случае:
>>> zip(fields, row)
[('parliament', '7'), ('name', 'Marta Andreasen'), ('country', 'United Kingdom'), ...]
Функция dict()
просто преобразует список пар в словарь.
>>> dict(zip(fields, row))
{'parliament': '7', 'name': 'Marta Andreasen', 'country': 'United Kingdom', ...}
**
- это способ преобразования словаря в список аргументов ключевого слова для функции. Итак, function(**{'key': 'value'})
является эквивалентом function(key='value')
. Поэтому в следующем примере вызов create(**dict(zip(field, row)))
эквивалентен:
create(parliament='7', name='Marta Andreasen', country='United Kingdom', ...)
Надеюсь, что это прояснит ситуацию.
Ответ 2
Как говорит SiggyF и только немного отличается от Joschua:
Создайте текстовый файл с вашей схемой, например:
CREATE TABLE politicians (
Parliament text,
Name text,
Country text,
Party_Group text,
National_Party text,
Position text
);
Создать таблицу:
>>> import csv, sqlite3
>>> conn = sqlite3.connect('my.db')
>>> c = conn.cursor()
>>> with open('myschema.sql') as f: # read in schema file
... schema = f.read()
...
>>> c.execute(schema) # create table per schema
<sqlite3.Cursor object at 0x1392f50>
>>> conn.commit() # commit table creation
Используйте модуль csv для чтения файла с данными, которые нужно вставить:
>>> csv_reader = csv.reader(open('myfile.txt'), skipinitialspace=True)
>>> csv_reader.next() # skip the first line in the file
['Parliament', 'Name', 'Country', ...
# put all data in a tuple
# edit: decoding from utf-8 file to unicode
>>> to_db = tuple([i.decode('utf-8') for i in line] for line in csv_reader)
>>> to_db # this will be inserted into table
[(u'7', u'Marta Andreasen', u'United Kingdom', ...
Вставить данные:
>>> c.executemany("INSERT INTO politicians VALUES (?,?,?,?,?,?);", to_db)
<sqlite3.Cursor object at 0x1392f50>
>>> conn.commit()
Убедитесь, что все прошло так, как ожидалось:
>>> c.execute('SELECT * FROM politicians').fetchall()
[(u'7', u'Marta Andreasen', u'United Kingdom', ...
Edit:
И так как вы декодировали (в unicode) на входе, вам нужно обязательно закодировать на выходе.
Например:
with open('encoded_output.txt', 'w') as f:
for row in c.execute('SELECT * FROM politicians').fetchall():
for col in row:
f.write(col.encode('utf-8'))
f.write('\n')
Ответ 3
Вы можете прочитать данные с помощью модуля csv. Затем вы можете создать инструкцию sql вставки и использовать метод executemany:
cursor.executemany(sql, rows)
или используйте add_all, если вы используете sqlalchemy.
Ответ 4
Вы спросили, что делает строка create (** dict (zip (fields, row))).
Я не знаю, как ответить прямо на ваш комментарий, поэтому я постараюсь ответить на него здесь.
zip принимает несколько списков в качестве аргументов и возвращает список соответствующих элементов в виде кортежей.
zip (list1, list2) = > [(list1 [0], list2 [0]), (list1 [1], list2 [1]),....]
dict принимает список двухэлементных кортежей и возвращает словарь, сопоставляющий каждый элемент (ключ) каждого кортежа со своим вторым элементом (значением).
create - это функция, которая принимает аргументы ключевого слова. Вы можете использовать ** some_dictionary, чтобы передать этот словарь в функцию как аргументы ключевого слова.
create (** {'name': 'john', 'age': 5}) = > create (name= 'john', age = 5)
Ответ 5
Что-то вроде следующего должно работать: (не проверено)
# Open database (will be created if not exists)
conn = sqlite3.connect('/path/to/your_file.db')
c = conn.cursor()
# Create table
c.execute('''create table representatives
(parliament text, name text, country text, party_group text, national_party text, position text)''')
f = open("thefile.txt")
for i in f.readlines():
# Insert a row of data
c.execute("""insert into representatives
values (?,?,?,?,?,?)""", *i.split(", ")) # *i.split(", ") does unpack the list as arguments
# Save (commit) the changes
conn.commit()
# We can also close the cursor if we are done with it
c.close()