Как можно иметь в наборе Python 2 одинаковых элемента? Это ошибка Python?
type(data_chunks)
<class 'set'>
len(data_chunks)
43130
same = [x for x in data_chunks if x.md5==chunk.md5]
[<Model.Chunk.Chunk o...x0DB40870>, <Model.Chunk.Chunk o...x0DB40870>]
len(same)
2
same[0] is same[1]
True
same[0] == same[1]
True
len(set(same))
1
Но когда я строю из него словарь, дублирование удаляется!
len({k:k.product_id for k in data_chunks})
43129
Почему это работает для словаря, а не для набора? Я думал, что это была коллизия в хеш-таблице, но на самом деле дублированный объект - это тот же объект, поэтому он не был найден в поиске набора, когда был добавлен следующий элемент (?)
Дополнительная информация:
Chunk
определил методы__hash__
и__eq__
- Python 3.7.2
- Я понял, что у
Chunk
есть некоторые свойства, которые вызывают ошибку - это не должно быть важно, поскольку они не вызываются - текущая строка кода:
data_chunks = data_chunks | another_set
- интерактивная подсказка во время сеанса отладки в vscode
- при запуске кода это случается иногда
- но во время этого сеанса отладки создание новых наборов из data_chunks всегда имеет одинаковую длину
РЕДАКТИРОВАТЬ
Реализация чанка
class Chunk(object):
def __init__(self,
md5,
size=None,
compressedMd5=None,
# ... (more elements)
product_id=None):
self.md5 = md5
self.product_id = product_id
# (etc.)
def __eq__(self, other):
if self.compressedMd5:
return self.compressedMd5 == other.compressedMd5 and self.product_id == other.product_id
return self.md5 == other.md5 and self.product_id == other.product_id
def __hash__(self):
return self.name.__hash__()
@property
def name(self):
return self.compressedMd5 if self.compressedMd5 is not None else self.md5
==================
ИЗМЕНИТЬ Хорошо, поэтому код выглядит следующим образом:
repository
- дескриптор json
chunking_strategy = ...
- в основном класс, который хранит настройки, например, что блоки будут сжиматься.
result_handler = Strategy.DefaultResultHandler(repository)
Создает уникальные хэши объектов чанков в репозитории: чанков и сопоставление соответствующих файлов. Позже он вызовет задания сжатия, а затем установит compressedMd5 и другие свойства существующих фрагментов.
generation_strategy = Strategy.CachingGenerationStrategy(
result_handler,
Settings().extra_io_threads,
)
data_chunks = Strategy.DepotChunker(repository, chunking_strategy, generation_strategy)()
при инициализации DeputChunker: задания на фрагменты задач подготавливаются на основе настроек chunking_strategy. Затем generation_strategy.__call__
метод обрабатывает все задания: файлы, которые нужно разделить на небольшие части на основе ранее определенных объектов Chunk. Это сделано в multiprocessing.Pool
. После создания физических блоков они проверяют md5, и объект Chunk обновляется на compressedMd5
, compressedSize
и product_id
. Затем (сразу после изменения объекта Chunk) в набор добавляются объекты chunk. Этот набор возвращен из DepotChunker
Затем сжатые фрагменты сохраняются в кеше.
Затем все data_chunks - это поиск небольших объектов с небольшим размером, из которых создаются физические фрагменты (в буфере памяти), состоящие из объединенных небольших файлов. Назовем их smallFilesChunks. Они добавлены к data_chunks
:
sfChunk = Chunk(
sfCompressedContentMD5, # yes I see that this is compressed md5 - it was intended for some reason I don't know
size=sfSize,
compressedMd5=sfCompressedContentMD5,
compressedSize=sfCompressedSize,
product_id=productId
)
if not sfChunk in data_chunks: # purly sanity check
data_chunks.add(sfcChunk)
В конце создаются мета-файлы, которые также разбиваются на части и добавляются в data_chunks
Тогда мета-файлы - это дампы, и они тоже разбиты на части.
for depot in manifest_depots:
data_chunks = data_chunks | simpleChunker(depot)
В этот момент сеанс отладчика с самого начала был записан
Chunk
, чтобы выявить какие-либо проблемы с хешированием. - person Rach Sharp   schedule 23.07.2019Chunk
изменчив? - person NPE   schedule 23.07.2019__hash__
использует метод__hash__
наcompressedMd5
илиmd5
- они реализуют__hash__
одинаково? Вы составляете списокsame
на основе равенства только атрибутаmd5
, тогда как__hash__
is и__eq__
также проверяют другие атрибуты. - person Jeff   schedule 23.07.2019