【问题标题】:Python 2.7.11 os.rename issues and weird execution orderPython 2.7.11 os.rename 问题和奇怪的执行顺序
【发布时间】:2016-04-22 22:44:18
【问题描述】:

我正在尝试编写一个简单的脚本来检查文件名称中是否包含数字,如果有则删除它们。这是我的代码:

import os

directory = raw_input("Enter a path string: ")
print "This will now delete all numbers from the files in %s." %directory

for filename in os.listdir(directory):
    print filename
    for s in filename:
        if s.isdigit():
            print filename
            path = os.path.join(directory, filename)
            print path
            target = os.path.join(directory, filename.replace(s, ""))
            print target
            os.rename(path, target)

print "Done."

当我运行它时,我收到以下错误:

Traceback (most recent call last):
File "EditFilename.py", line 15, in <module>
os.rename(path, target)
NameError: name 'path' is not defined

这很奇怪,因为 path 已明确定义。如果我在 for 循环上方将path 定义为path = "Nothing",则会收到此错误:

File "EditFilename.py", line 16, in <module>
os.rename(path, target)
OSError: [Errno 2] No such file or directory

我正在关注this 链接中明显有效的内容,但我无法让我的代码正常工作。似乎os.rename(path, target) 行在path = os.path.join(directory, filename) 行之前执行!

提前感谢您的帮助,经过四个小时的谷歌搜索,我不知道该怎么办。

【问题讨论】:

  • 您是否 100% 确定您的缩进是正确的?也许rename 行根本不在if 块内。
  • 您得到的NameError 可能意味着您在脚本运行之间没有正确地重新启动Python。您在此处发布的代码不会抛出NameError,不会。
  • 查看问题的来源,您似乎在混合制表符和空格。 不要那样做!
  • 不是一个直接的答案,但你为什么不使用正则表达式(re)呢? pastebin.com/c81WtXP0
  • 我不知道存在这样的模块。感谢您引起我的注意,我仍在阅读它,但看起来它可能会进一步简化事情。

标签: python execution


【解决方案1】:

您发布的代码不会抛出NameError;确保在运行您编辑的代码之前正确地重新启动了 Python。

但是,您确实有其他问题会导致OSError。你永远不会退出你的for s in filename: 循环。因此,如果您的文件名中有多个数字,您可以尝试多次重命名:

>>> filename = 'hunter42'
>>> for s in filename:
...     if s.isdigit():
...         print 'renaming {} to {}'.format(filename, filename.replace(s, ''))
...
renaming hunter42 to hunter2
renaming hunter42 to hunter4

由于hunter42 已重命名为hunter2,您不能再次将其重命名为其他名称。

改用any() function,只测试一次数字,而不是在for循环中:

for filename in os.listdir(directory):
    if any(s.isdigit() for s in filename):
        path = os.path.join(directory, filename)
        target = os.path.join(directory, filename.translate(None, '0123456789'))
        os.rename(path, target)

我在这里使用str.translate()从文件名中删除数字:

>>> filename.translate(None, '01234567890')
'hunter'

你也可以翻译名字,如果和原来的不一样,然后重命名:

for filename in os.listdir(directory):
    newname = filename.translate(None, '0123456789')
    if filename != newname:
        path = os.path.join(directory, filename)
        target = os.path.join(directory, newname)
        os.rename(path, target)

【讨论】:

  • 虽然这当然是真的,但我看不出多次重命名文件会导致 OP 遇到的名称错误或“没有这样的文件”错误...
  • @tobias_k: 因为旧文件已经重命名了,所以不能再重命名。
  • @tobias_k: 将hunter42 重命名为hunter2 后,尝试将hunter42 重命名为hunter4 将不起作用。请注意filename 引用是未更改 在循环中!
  • 啊,对,filename 没有更新,新名称只存储在 target... 但仍然,NameError 必须有其他原因(请参阅我的评论问题)。
  • NameError 由于缩进问题被抛出,就像 tobias_k 说的那样。我不知道存在any()filename.translate 方法,我已经实现了它们。谢谢你们的帮助!
【解决方案2】:

查看您问题的标记源,您似乎在为 Python 缩进混合制表符和空格。不要这样做!这会严重混淆您的 Python 解释器,并导致个别行与不同的块相关联。

很难确定您的缩进究竟是多少,因为问题中的代码块有额外的缩进,但是,if 块中的前三行缩进了 3 个制表符和 4 个空格,并且以下三行包含 8 个空格、1 个制表符和另外 4 个空格。

因此,您的 Python 解释器看到的可能更像这样:

for s in filename:
    if s.isdigit():
        print filename
        path = os.path.join(directory, filename)
        print path
    target = os.path.join(directory, filename.replace(s, ""))
    print target
    os.rename(path, target)

也就是说,os.rename总是执行,即使 path 之前没有在 if 块中定义,并且如果您在开始时定义 path = "Nothing",它当 Python 遇到第一个 os.rename 时,该值仍然存在。

要解决这个问题,只需将所有缩进转换为制表符或空格(使用的有点像question of taste)。大多数文本编辑器都会为您执行此操作,如果只是缩进然后再删除所有内容(即按 Ctrl-A、Tab、Shift-Tab)。

【讨论】:

  • 就是这样,非常感谢!我仍然习惯缩进对解释器很重要的事实。
猜你喜欢
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多