Can a line of Python code know its indentation nesting level?
<p>From something like this:</p>

<pre><code>print(get_indentation_level())

    print(get_indentation_level())

        print(get_indentation_level())
</code></pre>

<p>I would like to get something like this:</p>

<pre><code>1
2
3
</code></pre>

<p>Can the code read itself in this way?</p>

<p>All I want is the output from the more nested parts of the code to be more nested. In the same way that this makes code easier to read, it would make the output easier to read. </p>

<p>Of course I could implement this manually, using e.g. <code>.format()</code>, but what I had in mind was a custom print function which would <code>print(i*' ' + string)</code> where <code>i</code> is the indentation level. This would be a quick way to make readable output on my terminal. </p>

<p>Is there a better way to do this which avoids painstaking manual formatting?</p>

<p>You can use <code>sys.current_frame.f_lineno</code> in order to get the line number. Then in order to find the number of indentation level you need to find the previous line with zero indentation then be subtracting the current line number from that line's number you'll get the number of indentation:</p>

<pre><code>import sys
current_frame = sys._getframe(0)

def get_ind_num():
    with open(__file__) as f:
        lines = f.readlines()
    current_line_no = current_frame.f_lineno
    to_current = lines[:current_line_no]
    previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())
    return current_line_no - previous_zoro_ind
</code></pre>

<p>Demo:</p>

<pre><code>if True:
    print get_ind_num()
    if True:
        print(get_ind_num())
        if True:
            print(get_ind_num())
            if True: print(get_ind_num())
# Output
1
3
5
6
</code></pre>

<p>If you want the number of the indentation level based on the previouse lines with <code>:</code> you can just do it with a little change:</p>

<pre><code>def get_ind_num():
    with open(__file__) as f:
        lines = f.readlines()

    current_line_no = current_frame.f_lineno
    to_current = lines[:current_line_no]
    previous_zoro_ind = len(to_current) - next(i for i, line in enumerate(to_current[::-1]) if not line[0].isspace())
    return sum(1 for line in lines[previous_zoro_ind-1:current_line_no] if line.strip().endswith(':'))
</code></pre>

<p>Demo:</p>

<pre><code>if True:
    print get_ind_num()
    if True:
        print(get_ind_num())
        if True:
            print(get_ind_num())
            if True: print(get_ind_num())
# Output
1
2
3
3
</code></pre>

<p>And as an alternative answer here is a function for getting the number of indentation (whitespace):</p>

<pre><code>import sys
from itertools import takewhile
current_frame = sys._getframe(0)

def get_ind_num():
    with open(__file__) as f:
        lines = f.readlines()
    return sum(1 for _ in takewhile(str.isspace, lines[current_frame.f_lineno - 1]))
</code></pre>

python reflection metaprogramming indentation tokenize