os.walk разные порядок папок на Mac и Linux? - PullRequest
0 голосов
/ 19 февраля 2019

Учитывая следующую файловую структуру,

├── 0=ocfl_object_1.0
├── inventory.json
├── inventory.json.md5
├── v1
│   ├── content
│   │   ├── foo.xml
│   │   └── level1
│   │       └── level2
│   │           └── bar.txt
│   ├── inventory.json
│   └── inventory.json.md5
└── v2
    ├── content
    │   └── duck.txt
    ├── inventory.json
    └── inventory.json.md5

Мне интересно, возможно ли, что функция Python os.walk возвращает папки в разных порядках на Mac и Linux?Оба используют python 3.5.

Mac:

In [15]: for root,folders,files in os.walk('foo/bar'): 
    ...:     print(folders,files) 
    ...:                                                                                                                                                                                                                                                                                   
['v1', 'v2'] ['inventory.json', '0=ocfl_object_1.0', 'inventory.json.md5']
['content'] ['inventory.json', 'inventory.json.md5']
['level1'] ['foo.xml']
['level2'] []
[] ['bar.txt']
['content'] ['inventory.json', 'inventory.json.md5']
[] ['duck.txt']

В Linux:

In [54]: for root,folders,files in os.walk('foo/bar'): 
    ...:     print(folders,files) 
    ...:                                                                                                                                                                                                                                                                                   
['v2', 'v1'] ['inventory.json.md5', 'inventory.json', '0=ocfl_object_1.0']
['content'] ['inventory.json.md5', 'inventory.json']
[] ['duck.txt']
['content'] ['inventory.json.md5', 'inventory.json']
['level1'] ['foo.xml']
['level2'] []
[] ['bar.txt']

В случае Mac выглядит, как будто папка v1встречается первым, в то время как в Linux это v2.Любое понимание того, почему это может иметь место?

1 Ответ

0 голосов
/ 19 февраля 2019

См. Документацию по os.walk, соответствующая часть:

Изменено в версии 3.5: Эта функция теперь вызывает os.scandir() вместо os.listdir(), что делает его быстрее за счет сокращения числа вызовов до os.stat().

А затем в os.scandir():

Возвратитератор os.DirEntry объектов, соответствующих записям в каталоге, заданном путем. Записи приводятся в произвольном порядке , а специальные записи '.' и '..' не включаются.

Независимо от listdir() или scandir(), обав любом случае возвращается в произвольном порядке.

Короче говоря, порядок не ожидается.


Сказав это, вы должны иметь возможность манипулировать dirnames в цикле на основеэта часть:

Когда topdown равен True, вызывающий абонент может изменить dirnames список на месте (возможно, используяdel или slice (присваивание), а walk() будут возвращаться только в подкаталоги, имена которых остаются в dirnames ;это можно использовать для сокращения поиска, , для наложения определенного порядка посещения или даже для информирования walk() о каталогах, которые вызывающий абонент создает или переименовывает, прежде чем он возобновит walk() снова.Изменение dirnames , когда topdown равно False, не влияет на поведение обхода, поскольку в режиме снизу вверх каталоги в dirnames создаются до dirpath сам генерируется.

Так что если вы folders.sort(), он должен работать на основе вашего sorted заказа.Я только что попробовал, и это работает.Я также выделил ключевую часть на месте - folders необходимо отсортировать на месте, чтобы os.walk() принял заказ:

for root,folders,files in os.walk('foo/bar'): 
    folders.sort()   # <--- sort your folders to impose the order. 
    print(folders,files) 
...