299

I have some Python code that have inconsistent indentation. There is a lot of mixture of tabs and spaces to make the matter even worse, and even space indentation is not preserved.

The code works as expected, but it's difficult to maintain.

How can I fix the indentation (like HTML Tidy, but for Python) without breaking the code?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shay Erlichmen
  • 31,691
  • 7
  • 68
  • 87
  • can you review this link and provide your inputs on how to use reindent.py module--http://stackoverflow.com/questions/12132481/installing-reindent-python/12132523#comment16227062_12132523 – user1050619 Aug 26 '12 at 18:05
  • As mentioned below by @andy-hayden look at this related question - basically `autopep8` provides indentation and much much more: http://stackoverflow.com/questions/14328406/tool-to-convert-python-code-to-be-pep8-compliant – Pierz Dec 01 '14 at 09:41
  • 3
    This is an insanely useful question, I find myself needing to do this quite often. It's not about "recommending a tool" so much as "how to do it". – Andy Hayden Feb 22 '16 at 06:20

14 Answers14

302

Use the reindent.py script that you find in the Tools/scripts/ directory of your Python installation:

Change Python (.py) files to use 4-space indents and no hard tab characters. Also trim excess spaces and tabs from ends of lines, and remove empty lines at the end of files. Also ensure the last line ends with a newline.

Have a look at that script for detailed usage instructions.


NOTE: If your linux distro does not have reindent installed by default with Python:

Many linux distros do not have reindent installed by default with python --> one easy way to get reindent is to do pip install reindent.

p.s. An alternative to pip is to use your distros package manager (i.e. apt-get, yum, dnf) but then you need to figure out what package has the command line tool because each distro has the tool in a different package.

Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 57
    Unfortunately, it's not part of the normal Python install on Debian and Ubuntu; it's split out into the `python-examples` package. – ephemient Jun 21 '09 at 20:03
  • 17
    Excellent! So all that Debian and Ubuntu users need do is to apt-get that package. Alternatively, the script is also at http://svn.python.org/view/python/trunk/Tools/scripts/reindent.py?revision=66903&view=markup . – Alex Martelli Jun 21 '09 at 20:52
  • Works like a charm, I left the question open for a while so you can enjoy more up votes. BTW, is there a way to force constant indention per file? I want python to allow only 4 spaces per indentation level and fail the parsing otherwise. If the answer is yes then I will open a new question. – Shay Erlichmen Jun 22 '09 at 09:41
  • 9
    @Shay Erlichmen: Try "python -tt yourscript.py" – nosklo Jun 22 '09 at 12:28
  • @nosklo's right, -tt gives errors on inconsistent tab usage (however it does tolerate _consistent_ tab usage, 3-space indent vs 4, etc, so it's still more permissive than @Shay would want). – Alex Martelli Jun 22 '09 at 14:52
  • 10
    Fedora/RedHat/CentOS users should install the "python-tools" package. – Cristian Ciupitu Jun 30 '09 at 18:41
  • 29
    Just to add to ephemient's comment: once `python-examples` is installed, you'll find reindent in `/usr/share/doc/pythonX.X/examples/Tools/scripts/reindent.py`. – Larry Hastings Feb 28 '10 at 00:35
  • 2
    but what if i want tabs? (why? because it’s The Right Way™). seriously: this script is no good if it isn’t even flexible enough to do this. – flying sheep May 17 '11 at 12:55
  • 3
    Following up to @LarryHastings, currently after installing `python-examples` the script is at `/usr/share/doc/libpythonX.Y/examples/Tools/scripts/reindent.py` (note that `pythonX.Y` became `libpythonX.Y`). – mernst Mar 31 '13 at 03:06
  • how to use this script on Windows ? – mounaim Jan 31 '15 at 16:24
  • 1
    @mounaim, find where `reindent.py` lives on your Windows installation and run it with your installation of Python just like you'd run any other Python script. If you can't find it see http://svn.python.org/projects/python/trunk/Tools/scripts/reindent.py (for a Python 2 version) or https://github.com/certik/python-3.2/blob/master/Tools/scripts/reindent.py (for a Python 3 version). The start of each script gives copious instructions. – Alex Martelli Jan 31 '15 at 16:35
  • On my Raspberry Pi running Raspbian, after having installed python3.2-examples by apt-get, I found the reindent.py script in /usr/share/doc/libpython3.2/examples/scripts/reindent.py. (No Tools directory.) – ArVID220u Jul 21 '15 at 17:10
  • 4
    On Mac with brew, I used `find /usr | grep reindent` and found `/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/share/doc/python3.5/examples/Tools/scripts/reindent.py elevator_test.py` – Dorian Jan 13 '16 at 01:06
  • Is there a problem with `windows 64 bit` `pip` and `powershell`? It is not working in that scenario.http://stackoverflow.com/questions/35583682/reindent-py-not-working-in-windows7 – malhar Feb 23 '16 at 17:07
  • I don't know why 200+ votes on this, just tried it and it didn't work on tab/spaced mixed file (win 7 python 3.4 – mstram Dec 10 '16 at 16:23
  • Following @Dorian instructions, use `find /usr | grep reindent` and in **Arch Linux** 2019 find at `/usr/lib/python3.8/Tools/scripts/reindent.py`. – 7beggars_nnnnm Jan 11 '20 at 14:43
  • still works like a charm in **2022** - works for multiple **tabs**, even if I have a function with indentation level of 3 tabs or 4 tabs or many more or tabs/spaces mixed (as long as the indentation rule is followed in the function as a rule - can be different for different functions) , it works perfectly - why use something else, when there is something that is already shipped in the python release itself. – aspiring1 Apr 18 '22 at 17:38
  • **`python-examples` is not available** for Debian 12 in any APT sources. – Константин Ван Mar 19 '23 at 11:35
68

I would reach for autopep8 to do this:

$ # see what changes it would make
$ autopep8 path/to/file.py --select=E101,E121 --diff

$ # make these changes
$ autopep8 path/to/file.py --select=E101,E121 --in-place

Note: E101 and E121 are pep8 indentation (I think you can simply pass --select=E1 to fix all indentation related issues - those starting with E1).

You can apply this to your entire project using recursive flag:

$ autopep8 package_dir --recursive --select=E101,E121 --in-place

See also Tool to convert Python code to be PEP8 compliant.

Community
  • 1
  • 1
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535
60

autopep8 -i script.py

Use autopep8

autopep8 automagically formats Python code to conform to the PEP 8 nullstyle guide. It uses the pep8 utility to determine what parts of the nullcode needs to be formatted. autopep8 is capable of fixing most of the nullformatting issues that can be reported by pep8.

pip install autopep8
autopep8 script.py    # print only
autopep8 -i script.py # write file
Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
59

If you're using Vim, see :h retab.

                                                        *:ret* *:retab*
:[range]ret[ab][!] [new_tabstop]
                        Replace all sequences of white-space containing a
                        <Tab> with new strings of white-space using the new
                        tabstop value given.  If you do not specify a new
                        tabstop size or it is zero, Vim uses the current value
                        of 'tabstop'.
                        The current value of 'tabstop' is always used to
                        compute the width of existing tabs.
                        With !, Vim also replaces strings of only normal
                        spaces with tabs where appropriate.
                        With 'expandtab' on, Vim replaces all tabs with the
                        appropriate number of spaces.
                        This command sets 'tabstop' to the new value given,
                        and if performed on the whole file, which is default,
                        should not make any visible change.
                        Careful: This command modifies any <Tab> characters
                        inside of strings in a C program.  Use "\t" to avoid
                        this (that's a good habit anyway).
                        ":retab!" may also change a sequence of spaces by
                        <Tab> characters, which can mess up a printf().
                        {not in Vi}
                        Not available when |+ex_extra| feature was disabled at
                        compile time.

For example, if you simply type

:ret

all your tabs will be expanded into spaces.

You may want to

:se et  " shorthand for :set expandtab

to make sure that any new lines will not use literal tabs.


If you're not using Vim,

perl -i.bak -pe "s/\t/' 'x(8-pos()%8)/eg" file.py

will replace tabs with spaces, assuming tab stops every 8 characters, in file.py (with the original going to file.py.bak, just in case). Replace the 8s with 4s if your tab stops are every 4 spaces instead.

ephemient
  • 198,619
  • 38
  • 280
  • 391
17

Using Vim, it shouldn't be more involved than hitting Esc, and then typing...

:%s/\t/    /g

...on the file you want to change. That will convert all tabs to four spaces. If you have inconsistent spacing as well, then that will be more difficult.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ben Hughes
  • 14,075
  • 1
  • 41
  • 34
10

There is also PythonTidy (since you said you like HTML Tidy).

It can do a lot more than just clean up tabs though. If you like that type of thing, it's worth a look.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Hildebrandt
  • 2,724
  • 28
  • 26
6

On most UNIX-like systems, you can also run:

expand -t4 oldfilename.py > newfilename.py

from the command line, changing the number if you want to replace tabs with a number of spaces other than 4. You can easily write a shell script to do this with a bunch of files at once, retaining the original file names.

Crowman
  • 25,242
  • 5
  • 48
  • 56
  • 2
    Note that using the same file doesn't work and leaves you with an empty file, but this answer actually works and I use it when I need to convert my tabs to spaces. Could anyone explain the downvote? I'll up it +1. – S. Kerdel Jul 18 '16 at 14:34
  • Is there any possible way to recover the overwritten file? Just used the above method and my day's worth of code vanished *facepalm*. Thanks – Simas Mar 19 '20 at 10:24
5

The reindent script did not work for me, due to some missing module. Anyway, I found this sed command which does the job perfect for me:

sed -r 's/^([  ]*)([^ ])/\1\1\2/' file.py
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin Vegter
  • 136
  • 9
  • 32
  • 56
4

If you're lazy (like me), you can also download a trial version of Wingware Python IDE, which has an auto-fix tool for messed up indentation. It works pretty well. http://www.wingware.com/

Yansky
  • 4,580
  • 8
  • 29
  • 24
2

Try Emacs. It has good support for indentation needed in Python. Please check this link http://python.about.com/b/2007/09/24/emacs-tips-for-python-programmers.htm

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arnkrishn
  • 29,828
  • 40
  • 114
  • 128
1

Try IDLE, and use Alt + X to find indentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
anshuman
  • 3,496
  • 1
  • 19
  • 13
0

I have a simple solution for this problem. You can first type ":retab" and then ":retab!", then everything would be fine

hanqiang
  • 567
  • 1
  • 7
  • 17
0

In case of trying to find tool to make your 2-space indented python script to a tab indented version, just use this online tool:

https://www.tutorialspoint.com/online_python_formatter.htm

Mehrdad Salimi
  • 1,400
  • 4
  • 16
  • 31
0

There is also a Google awesome project called YAPF

It can automatically reformat the whole project or check if the project has correct indentation/format. I used that in a commercial project and I recommend that.

Kamil Kuczaj
  • 193
  • 1
  • 8