Порядок итерации через dict.items()

#python #python-3.x #dictionary

Вопрос:

TLDR:
если я создаю словарь в два отдельных раза из одних и тех же данных, обработанных одинаково, должен ли порядок dictionary.items() быть одинаковым каждый раз?

Здравствуйте,

У меня есть словарь linked_strain_acc , в котором около 2000 ключей (имен напряжений), и каждый ключ имеет другой словарь в качестве значения ( data ).

 linked_strain_acc = {'strain1' : {'gcf' : ['gcf1', 'gcf'..],
                                  'key2' : val2,
                                  .........},
                    'strain2' :  {.........},
                    ..........
                    'strain2000' :  {.........}}
          
 

Я перебираю ключ ( 'gcf' ) в каждом data словаре, который содержит список gcf идентификаторов. Я использую gcf идентификаторы для создания URL-адреса для очистки, после проверки того, что он еще не был очищен.

 directory = r'C:Usersu03132tk.spyder-py3scrape_dsmzzip_files'
count = 0
start = time.time()
#allows you to stop and start
current_files = os.listdir(directory)
for strain,data in linked_strain_acc.items():
    for gcf in data['gcf']:
        count =1
        filename = f'{strain}__{gcf}.zip'
        if filename not in current_files:
            download_url = f'https://antismash-db.secondarymetabolites.org/output/{gcf}/{gcf}.zip'
            response = requests.get(download_url)
            with open(fr'{directory}{filename}', "wb") as infile:
                infile.write(response.content)
            print (f'downloaded {strain}, {gcf}')
        else:
            print (f'{strain}, {gcf} already scraped')
        if countP == 0:
            print (f'downloaded {count} jsons - script has been running for {round((time.time() - start)/60, 1)} minutes')
 

Вопрос

Я уже очистил около 1500 gcf URL-адресов и загрузил файлы (из общего числа 2000). Когда я снова запустил его сегодня утром, вместо того, чтобы печатать ‘{strain}, {gcf} уже очищенный’ для первых 1500 операторов печати, он чередовался между парой сообщений печати ‘{strain}, {gcf} уже очищенный’ и ‘загруженный {strain}, {gcf}’ печатьоператоры. Это означает, что порядок словаря linked_strain_acc изменился.

Я создал этот словарь из CSV — файла , который обрабатывался точно таким же образом каждый раз , чтобы сделать linked_strain_acc . Почему порядок диктовки должен измениться, или я что-то упускаю? Я знаю, что порядок dict key / val не упорядочен, например, по алфавиту или размеру, но я думаю, что он будет поддерживаться, когда он будет построен из точно таких же данных.

Спасибо!

Комментарии:

1. На какой версии Python вы работаете? Словари упорядочены по порядку вставки после 3.7.

2. привет, спасибо за ваш ответ — я 3.7, что означает упорядоченная вставка?

3. Вы уверены, что ваш URL-адрес указан правильно? Например, {gcf}/{gcf} в конце загрузки, когда все остальные строки кажутся {strain} {gcf} . Порядок элементов в словаре Python теперь исправлен для нескольких версий; кажется более вероятным, что проблема возникает из-за ручной очистки веб-страниц при создании URL-адресов или восстановлении CSV-файлов или использовании os.listdir() для чего-то другого, который имеет произвольный порядок.

4. Привет, kcsquared, я настолько уверен, насколько могу быть — я извлекаю их из онлайн-базы данных с помощью опции «загрузить файл», которая имеет «….. /gcf/gcf.zip ‘формат URL-адреса. Я получаю сами gcfs из сводного csv-файла результатов запроса, выводимого одной и той же базой данных, и все мои файлы, похоже, загружаются нормально (поскольку у меня их 1500, и я вручную проверил пару, они выглядят нормально). Сбивает с толку то, что в этих случаях не следует даже запускать webscraping — наличие файла в каталоге должно блокировать его запуск (и порядок os. listdir() не должен влиять на тесты присутствия).

5. Кроме того, я не перестраиваю csv, он всегда работает с одного и того же файла и обрабатывает его одним и тем же способом (я просто перезапускаю один и тот же скрипт, поэтому ничего не меняется — он просто проверяет то, что он уже нашел).

Ответ №1:

В более старых версиях python использовал пулы строк для эффективного хранения более длинных строк путем объединения более коротких общих сегментов. Каждый раз, когда вы создаете строку, она может изменять пул и, следовательно, порядок. Строки, которые вы динамически создаете в

 download_url = f'https://antismash-db.secondarymetabolites.org/output/{gcf}/{gcf}.zip'
 

может изменить пул в зависимости от вашей начальной точки. Для справки: https://en.wikipedia.org/wiki/String_interning

Комментарии:

1. Привет, Огузхан, спасибо за интересную идею — мне нужно будет поискать в Google о объединении, никогда не слышал об этом. Однако, конечно, это не было бы проблемой здесь, поскольку gcf определяется перед f-строкой? и f-строка не определяет порядок, в котором выполняется итерация dict?

2. Тем не менее, он может изменить порядок. Я не уверен, есть ли способ визуализировать / отлаживать пул интернирования. Я рад, что могу помочь!