Как обновить маринованные файлы? - PullRequest
1 голос
/ 30 октября 2019

Так что я сохранил кучу функций в виде файла .pkl. Это код, который я использовал для первоначального сохранения файлов.

with open('variables.pkl', 'wb') as output:
    pickle.dump(embedding_weights, output, 2)
    pickle.dump(X1, output, 2)
    pickle.dump(X2, output, 2)
    pickle.dump(Y, output, 2)
    pickle.dump(X1_test, output, 2)
    pickle.dump(X2_test, output, 2)
    pickle.dump(Y_test, output, 2)
    pickle.dump(X1_nli, output, 2)
    pickle.dump(X2_nli, output, 2)
    pickle.dump(Y_nli, output, 2)
    pickle.dump(X1_test_nli, output, 2)
    pickle.dump(X2_test_nli, output, 2)
    pickle.dump(Y_test_nli, output, 2)
    pickle.dump(X1_test_matched, output, 2)
    pickle.dump(X2_test_matched, output, 2)
    pickle.dump(Y_test_matched, output, 2)
    pickle.dump(X1_test_mismatched, output, 2)
    pickle.dump(X2_test_mismatched, output, 2)
    pickle.dump(Y_test_mismatched, output, 2)
    pickle.dump(X2_two_sentences, output, 2)
    pickle.dump(X2_test_two_sentences, output, 2)
    pickle.dump(tokenizer, output, 2)

ПРИМЕЧАНИЕ : я получил эти данные как есть, и этот код использовался для их создания. Я не могу перезапустить приведенный выше код, так как это функции глубокого обучения, для вычисления которых требуются часы. Следовательно, я не смогу вносить какие-либо изменения в файл variables.pkl Размер файла был приблизительно 1,93 ГБ. После этого я захотел обновить файл X1_test и X2_test, используя следующий код:

with open('variables.pkl', 'wb') as output:
     pickle.dump(X1_test, output, 2)
     pickle.dump(X2_test, output, 2)

Насколько я понял, он просто обновит два файла. Вместо этого он удалил все файлы, и остались только эти два файла. Размер файла составляет всего 12,6 КБ сейчас. Интересно, что я сделал не так? Как я могу просто обновить указанные два файла, оставив все остальное таким же.

Ответы [ 3 ]

2 голосов
/ 30 октября 2019

pickle - это последовательность байтов, которую вы можете записать в файл. Вы можете записать несколько одинаковых огурцов один за другим в один и тот же файл, но, как правило, вы не можете удалить и заменить первый рассол или любые другие в середине файла.

1.) Вы открыли файл в режиме«wb», который усекает файл. поэтому все данные потеряны. но представьте, что вы бы открыли его по-другому в режиме «r +», например

для первого алгоритма обработки требуется, например, 300 байт, второй блок начинается таким образом со смещением 300.

Теперь представьте, что вы открываете файл врежим чтения / записи и запись нового консерванта со смещением файла 0. Однако, к сожалению, теперь вашему консерватору требуется 301 байт. Вы бы перезаписали первый байт второго засоленного объекта. Второй рассол, таким образом, станет нечитаемым, и будет даже довольно сложно найти позицию, если начнется третий объект рассола.

Что вы можете сделать вместо этого: Либо выполните полную запись чтения / изменения.

То есть считывание всех маринадов во временные переменные изменяет ту, которую вы хотите изменить, и записывает все обратно.

Другой альтернативой является использование модуля shelve (https://docs.python.org/3.6/library/shelve.html), который ведет себя как кусок соления.

Ваш код может выглядеть следующим образом:

import shelve

d = shelve.open("mydata.shlv")

d['embedding_weights'] = embedding_weights
d['X1'] = X1
d['X2'] = X2
d['Y'] = Y
d['X1_test'] = X1_test
d['X2_test'] = X2_test
d['Y_test'] = Y_test
d['X1_nli'] = X1_nli
d['X2_nli'] = X2_nli
d['Y_nli'] = Y_nli
d['X1_test_nli'] = X1_test_nli
d['X2_test_nli'] = X2_test_nli
d['Y_test_nli'] = Y_test_nli
d['X1_test_matched'] = X1_test_matched
d['X2_test_matched'] = X2_test_matched
d['Y_test_matched'] = Y_test_matched
d['X1_test_mismatched'] = X1_test_mismatched
d['X2_test_mismatched'] = X2_test_mismatched
d['Y_test_mismatched'] = Y_test_mismatched
d['X2_two_sentences'] = X2_two_sentences
d['X2_test_two_sentences'] = X2_test_two_sentences
d['tokenizer'] = tokenizer
d.close()

Однако, если вам нужно придерживаться текущего формата файла и у вас достаточно свободного места на диске, вы можетесделать что-то вроде:

with open('variables.pkl', 'rb') as input:
  with open("newvariables.pkl", "wb") as output:
    pickle.dump(pickle.load(input), output, 2) # embedding_weights
    pickle.dump(pickle.load(input), output, 2) # X1 
    pickle.dump(pickle.load(input), output, 2) # X2
    pickle.dump(pickle.load(input), output, 2) # Y
    pickle.load(input) # read and discard X1_test
    pickle.dump(new_X1_test, output, 2)
    pickle.load(input) # read and discard X2_test
    pickle.dump(new_X2_test, output, 2)
    pickle.dump(pickle.load(input), output, 2) # Y_test ...
    pickle.dump(pickle.load(input), output, 2) # X1_nli
    ...
# now you could rename variables.pkl to oldvariables.pkl
# and rename newvariables.pkl to variables.pkl
0 голосов
/ 30 октября 2019

Формат файла pickle является последовательным форматом. Таким образом, если вы измените один элемент, по крайней мере все, что находится позади этой позиции в файле, должно быть переписано. wb открывает файл для записи только в двоичном формате. Он перезаписывает файл, если файл существует. Если файл не существует, создается новый файл для записи.

Поскольку файл находится в двоичном формате, я не вижу способа обновить файл, хотя добавление по-прежнему возможно - проверьте ab format.

Чтобы решить вашу проблему, правильным способом было бы сначала распаковать файл в режиме чтения, загрузить содержимое файла в переменную Python, выполнить обновление переменной,а затем откройте файл в wb , чтобы перезаписать его. Ниже приведен код для выполнения следующего:

with open('variables.pkl', 'rb') as file:
    variable_dict = pickle.load(file)

variable_dict['X1_test'] = X1
variable_dict['X2_test'] = X2

with open('variables.pkl', 'wb') as file:
    pickle.dumps(variable_dict, file)
0 голосов
/ 30 октября 2019

Вместо выгрузки всех переменных непосредственно в файл одна за другой;создайте словарь с ключами, указывающими имя и значения переменной в качестве фактических данных.

Первоначальное сохранение:

with open('variables.pkl', 'wb') as output:
    d = {'X1': X1, 'X2': X2}
    pickle.dumps(d, output)

Обновление этих значений:

#Open existing
with open('variables.pkl', 'rb') as file:
    d = pickle.load(file)

#Update the values
d['X1'] = X1
d['X2'] = X2

#Save
with open('variables.pkl', 'wb') as file:
    pickle.dumps(d, file)
...