os.walk()在GitHub Actions与本地运行返回结果顺序不一致问题
解决os.walk()在GitHub Actions中返回路径无序的问题
我使用Python的os.walk()遍历目录,将目录名称及下属文件名写入文件以生成侧边栏配置。本地运行时路径顺序正常,但在GitHub Actions工作流中,os.walk()返回的base路径完全无序,导致生成的配置顺序混乱。
原代码实现
def refactor_sidebar(): collapsed = False open(SIDEBAR, "w").close() with open(SIDEBAR, "a", encoding="utf-8") as file: file.write("export default Sidebar = [\n") for base, _, files in os.walk(SOLUTION_FOLDER): if base == "./docs/solution": continue problem_index = base.removeprefix("./docs/solution/") print(base) file.write( " {\n" f' text: "{problem_index}",\n' " collapsible: true,\n" f" collapsed: {str(collapsed).lower()},\n" " items: [\n" ) for md in files: file.write( " {\n" f' text: "{md[:-3]}",\n' f' link: "/solution/{problem_index}/{md}",\n' " },\n" ) file.write(" ],\n" " },\n") if not collapsed: collapsed = True file.write("]")
运行结果对比
- 本地运行(有序):
./docs/solution/0001-0100 ./docs/solution/0101-0200 ./docs/solution/0201-0300 ./docs/solution/0301-0400 ./docs/solution/0401-0500 ./docs/solution/0501-0600 ./docs/solution/0601-0700 ./docs/solution/0701-0800 ./docs/solution/0801-0900 ./docs/solution/1001-1100 ./docs/solution/1101-1200 ./docs/solution/1201-1300 ./docs/solution/1401-1500 ./docs/solution/1501-1600 ./docs/solution/2201-2300
- GitHub Actions运行(无序):
./docs/solution ./docs/solution/0501-0600 ./docs/solution/1101-1200 ./docs/solution/1501-1600 ./docs/solution/0101-0200 ./docs/solution/2201-2300 ./docs/solution/0301-0400 ./docs/solution/1001-1100 ./docs/solution/0601-0700 ./docs/solution/0401-0500 ./docs/solution/0801-0900 ./docs/solution/0001-0100 ./docs/solution/0701-0800 ./docs/solution/1201-1300 ./docs/solution/1401-1500 ./docs/solution/0201-0300
问题原因
os.walk()的遍历顺序完全依赖底层文件系统的返回结果:
- 本地系统(如Windows NTFS、macOS APFS)默认会按名称排序返回目录;
- GitHub Actions使用的Linux系统(ext4文件系统)返回的是目录创建顺序或inode顺序,并非按名称排序。
解决方案:手动排序遍历结果
先收集所有需要处理的目录路径,按目录名的数字前缀排序后再处理;同时对每个目录下的文件也进行排序,确保输出完全有序。
修改后的代码:
def refactor_sidebar(): collapsed = False open(SIDEBAR, "w").close() # 收集所有需要处理的目录路径 dirs_to_process = [] for base, _, _ in os.walk(SOLUTION_FOLDER): if base != "./docs/solution": dirs_to_process.append(base) # 按目录名的起始数字排序(如0001-0100取0001转成整数排序) dirs_to_process.sort(key=lambda path: int(path.split("/")[-1].split("-")[0])) with open(SIDEBAR, "a", encoding="utf-8") as file: file.write("export default Sidebar = [\n") for base in dirs_to_process: problem_index = base.removeprefix("./docs/solution/") print(base) file.write( " {\n" f' text: "{problem_index}",\n' " collapsible: true,\n" f" collapsed: {str(collapsed).lower()},\n" " items: [\n" ) # 获取当前目录下的文件并排序 _, _, files = next(os.walk(base)) files.sort() for md in files: file.write( " {\n" f' text: "{md[:-3]}",\n' f' link: "/solution/{problem_index}/{md}",\n' " },\n" ) file.write(" ],\n" " },\n") if not collapsed: collapsed = True file.write("]")
内容的提问来源于stack exchange,提问作者rajput-hemant
相关产品推荐
相关产品推荐

