Python-行首注释

时间:2019-01-26 17:16:40

标签: python auto-indent

我继承了一些python 2.7代码,这些代码在每一行的开头都注释掉了代码段,这使我发疯。该代码分为多个文件,总行数超过5万行,因此,我正在寻找一种自动更正此问题的方法。并非所有注释都在各行的开头,但有些注释是。我尝试过reindent和autopep8,但是它们都不能解决此问题。这是一个示例:

def test_function():
    a = 1

# There are comments that are not indented!
# Usually with commented out code like this:
#    c = 5
#    if c > a:
#        a = c

    b = 5
    return a*b
print(test_function())

有时,即使缩进级别为4或5级,注释也位于行的开头。理想情况下,以上将转换为以下。请注意,这涉及到如何在代码行的注释之后调整之前的空白,以使它们以应有的方式注释。那将是理想的,但我什至会更高兴让它只在开始时添加空白,而在评论后不进行调整,这可能会容易得多。

def test_function():
    a = 1

    # There are comments that are not indented!
    # Usually with commented out code like this:
    # c = 5
    # if c > a:
    #     a = c

    b = 5
    return a*b
print(test_function())

在我自己尝试创建某些东西之前,有人知道是否已经有一些图书馆可以做到这一点?

2 个答案:

答案 0 :(得分:0)

我整理了一些天真的awk脚本,该脚本应该能够缩进您的评论:

#!/usr/bin/gawk -f
BEGIN{
    last_indent=0
}

{
    indent=match($0, /[^ ]/) - 1
    if (indent < 0) indent = 0
    comment=0
}

/^#/{
    comment=1
    if (last_indent > 0) {
        indent_str = sprintf("%*s", last_indent, " ")
        $0 = indent_str $0
    }
}

{
    print
    if (length($0) && ! comment) last_indent=indent
}

运行它:

$ cat src.py | ./reindent.awk

(对于您的示例文件,它应该这样做)在输入的python文件中打印出与注释前面的当前块相对应的多余空格。

我已经考虑过您对注释中的代码的额外要求可以调整,但这是不平凡的,因为脚本实际上必须对其处理的内容有相当的了解。

不用说,在大多数情况下,应该删除评论并将其保留不是一个整洁的做法,至少由于我们拥有源代码的版本控制系统(大约70年代初期)。


在一个简单的例子中,这也许甚至可以成功缩进注释中的代码:

#!/usr/bin/gawk -f
BEGIN{
    last_indent=0
    commented_code_indent = 0
}

{
    indent=match($0, /[^ ]/) - 1
    if (indent < 0) indent = 0
    comment=0
}

/^#/{
    comment=1
    if (last_indent > 0) {
        indent_str = sprintf("%*s", last_indent, " ")
    stripped = length($0)
    sub(/#  +/, "# ")
    stripped -= length($0)
    if (stripped > 0 && ! commented_code_indent) commented_code_indent = stripped
    if (commented_code_indent > 0) {
       indent_in_comment = stripped - commented_code_indent
       if (indent_in_comment > 0) {
           comment_indent_str = sprintf("%*s", indent_in_comment, " ")
           sub(/# /, "# " comment_indent_str)
       }
        }
    $0 = indent_str $0
    }
}

{
    print
    if (length($0) && ! comment) last_indent=indent
    if (! comment) commented_code_indent = 0
}

是的,现在来看,本来可能是更简单的选择,然后是awk。 :)

答案 1 :(得分:0)

此缩进以#开头的行与下一个非注释行的缩进级别相同:

import sys

def remove_excess_space(comments):
    """Remove excess whitespace after #"""
    excess = 0
    for line in comments:
        stripped = line.lstrip('#').lstrip()
        if excess == 0:
            excess = len(line) - len(stripped) - len('# ')
        if excess > 0:
            line = '#{}'.format(line[1 + excess:])
        yield line

def fix(filename):
    indentation = 0
    comments = []
    with open(filename, 'r') as f:
        for line in f:
            if line.startswith('#'):
                comments.append(line)
            else:
                stripped = line.lstrip()                
                if stripped and not stripped.startswith('#'):
                    # I'm assuming indentation is done with spaces, not tabs
                    indentation = len(line) - len(stripped)

                if comments:
                    # indent the comments using the same indenation as the next non-comment line
                    print(''.join(['{}{}'.format(' '*indentation, line)
                                   for line in remove_excess_space(comments)]), end='')
                    comments = []                    
                print(line, end='')

if __name__ == '__main__':
    filename = sys.argv[1]
    fix(filename)

如果我们调用此indent_comments.py然后运行:

indent_comments.py /path/to/script.py

打印

def test_function():
    a = 1

    # There are comments that are not indented!
    # Usually with commented out code like this:
    # c = 5
    # if c > a:
    #     a = c

    b = 5
    return a*b
print(test_function())

请注意,在某些极端情况下,此脚本会出错。例如, 并非以#开头的每一行都必须是注释:

print('''\
# This is not 
    a comment
''')

将成为

print('''\
    # This is not 
    a comment
''')