Title: `os.walk()` no longer supports late edits to `dirnames` · Issue #102932 · python/cpython · GitHub
Open Graph Title: `os.walk()` no longer supports late edits to `dirnames` · Issue #102932 · python/cpython
X Title: `os.walk()` no longer supports late edits to `dirnames` · Issue #102932 · python/cpython
Description: Prior to the fix for #89727, it was possible influence which subdirectories were visited by os.walk() even after the walk had descended into siblings of those subdirectories. Such "late" modifications no longer have any effect. This was ...
Open Graph Description: Prior to the fix for #89727, it was possible influence which subdirectories were visited by os.walk() even after the walk had descended into siblings of those subdirectories. Such "late" modificati...
X Description: Prior to the fix for #89727, it was possible influence which subdirectories were visited by os.walk() even after the walk had descended into siblings of those subdirectories. Such "late" ...
Opengraph URL: https://github.com/python/cpython/issues/102932
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"`os.walk()` no longer supports late edits to `dirnames`","articleBody":"Prior to the fix for #89727, it was possible influence which subdirectories were visited by `os.walk()` **even after** the walk had descended into siblings of those subdirectories. Such \"late\" modifications no longer have any effect.\r\n\r\nThis was [reported](https://github.com/python/cpython/issues/89727#issuecomment-1369298204) by @pochmann:\r\n\r\n\u003e I think you changed `os.walk`'s behavior. The recursive one supported late modifications of subdirs lists, due to being lazier. The iterative one doesn't (if I'm not mistaken... I can't test).\r\n\u003e \r\n\u003e With topdown, you can modify a directory's subdirs, for example remove one and it won't be visited. Usually you'd do that while your walk is on that parent directory. But with the recursive one, it was possible to do it later. With the iterative one, I don't think that works anymore.\r\n\u003e \r\n\u003e Here's a demo where I remove the second subdir after having walked onto the first:\r\n\u003e \r\n\u003e ```python\r\n\u003e import os\r\n\u003e \r\n\u003e # Create demo dir with three subdirs\r\n\u003e os.makedirs('demo/a')\r\n\u003e os.makedirs('demo/b')\r\n\u003e os.makedirs('demo/c')\r\n\u003e \r\n\u003e # Walk onto \"demo\"\r\n\u003e walk = os.walk('demo')\r\n\u003e demo = next(walk)\r\n\u003e print(demo)\r\n\u003e \r\n\u003e # Walk onto first subdir\r\n\u003e first = next(walk)\r\n\u003e print(first)\r\n\u003e \r\n\u003e # Remove the second subdir\r\n\u003e del demo[1][1]\r\n\u003e \r\n\u003e # Walk onto the remaining subdirs\r\n\u003e for x in walk:\r\n\u003e print(x)\r\n\u003e ```\r\n\u003e \r\n\u003e Output ([Try it online!](https://tio.run/##bZCxDoJADIb3e4pGB2HBGBdj4uQbuDgYh0OKXJArOarg02MLaqLhckPv69/@vdZPLsivN3Xoe1fVFBioMWYO@4CWETKsCDIXoHVcABcBEZp7KqQx1CSVLVHjaKHCpV3EEzSdpBeh4nO0txLIM8FM8cy0CnYyRaLRKBbpMMgOPHYcaSI2dXCeI@V/jXIx4feUZnxMFA6JofIgLR4on5Ov4YV89qnN8DYs4LQ6y/01UXXAyjrv/PW7kpwCdOA8qNPWgJzRrYv7/gU)), note that the second subdir wasn't walked:\r\n\u003e \r\n\u003e ```python\r\n\u003e ('demo', ['c', 'a', 'b'], [])\r\n\u003e ('demo/c', [], [])\r\n\u003e ('demo/b', [], [])\r\n\u003e ```\r\n\u003e \r\n\u003e [Excerpt from the recursive one](https://github.com/python/cpython/blob/a7a450f84a087421603170c2dad226bb881d4d9a/Lib/os.py#L412-L419):\r\n\u003e \r\n\u003e ```python\r\n\u003e for dirname in dirs:\r\n\u003e new_path = join(top, dirname)\r\n\u003e yield from _walk(new_path, topdown, onerror, followlinks)\r\n\u003e ```\r\n\u003e \r\n\u003e The iteration of `dirs` and the walking of the subdirs are intertwined. After walking a subdir, the paused iteration of `dirs` resumes. That allows the late modifications of `dirs` to have an effect.\r\n\u003e \r\n\u003e [Excerpt from the iterative one](https://github.com/python/cpython/blob/73097d91a64620ae7f620705864b84234d85cc82/Lib/os.py#L418-L425):\r\n\u003e \r\n\u003e ```python\r\n\u003e for dirname in reversed(dirs):\r\n\u003e new_path = join(top, dirname)\r\n\u003e stack.append(new_path)\r\n\u003e ```\r\n\u003e \r\n\u003e This eagerly puts all subdirs onto the stack, before they're getting walked, and then `dirs` is never used again. So modifying `dirs` during the subdirs walking doesn't have an effect anymore.","author":{"url":"https://github.com/barneygale","@type":"Person","name":"barneygale"},"datePublished":"2023-03-22T20:17:08.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/102932/cpython/issues/102932"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:4e2dbd35-c876-8401-3363-7498b5ff730c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E9A8:2B4646:13D5C1:19F2F7:696B3001 |
| html-safe-nonce | 771a60707a438b92faba5fdfb38a837f88246f2141c97631de92e18ba65abf9e |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFOUE4OjJCNDY0NjoxM0Q1QzE6MTlGMkY3OjY5NkIzMDAxIiwidmlzaXRvcl9pZCI6IjU4NTYzMDU2MjIwMzMzMTM3OTMiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 5175f01405977330bdb966258d38d7ab6bb4d53c7fdc6c9256951e3f1908669d |
| hovercard-subject-tag | issue:1636438630 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/python/cpython/102932/issue_layout |
| twitter:image | https://opengraph.githubassets.com/e3e06fdf41db5fd28ff683a07251fbbc7bcd9e9f95c863095222b08e6cb10426/python/cpython/issues/102932 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/e3e06fdf41db5fd28ff683a07251fbbc7bcd9e9f95c863095222b08e6cb10426/python/cpython/issues/102932 |
| og:image:alt | Prior to the fix for #89727, it was possible influence which subdirectories were visited by os.walk() even after the walk had descended into siblings of those subdirectories. Such "late" modificati... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | barneygale |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f99f7c1d70f01da5b93e5ca90303359738944d8ab470e396496262c66e60b8d |
| turbo-cache-control | no-preview |
| go-import | github.com/python/cpython git https://github.com/python/cpython.git |
| octolytics-dimension-user_id | 1525981 |
| octolytics-dimension-user_login | python |
| octolytics-dimension-repository_id | 81598961 |
| octolytics-dimension-repository_nwo | python/cpython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 81598961 |
| octolytics-dimension-repository_network_root_nwo | python/cpython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 82560a55c6b2054555076f46e683151ee28a19bc |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width