Prevent changing indentation from tabs to spaces

Question:

I have VSCode installed and python 3.6.8
I use tabs for my indentation. But when ever I save the file, all the tabs are being converted to spaces.
This might be because of the formatter I use, i.e. Black. How do I prevent the formatter from doing that(Do all your formatting except inter-changing indents with spaces)?

Thank you

Asked By: Phani Pavan

||

Answers:

Assuming you don’t have VS Code set up to insert space into tabs, then Black will very likely replace them with spaces as that’s the norm in the Python community and Black takes a very opinionated view on how to format Python code. You could try another formatter like yapf or autopep8 to see if they will leave physical tabs in.

But do note that the vast majority of the Python community uses spaces, so you are potentially facing an uphill battle.

Answered By: Brett Cannon

Not only ‘black’ but also ‘autopep8’ and ‘yapf’ will convert the tabs to spaces. And looks like both ‘black’, ‘autopep8’ and ‘yapf’ haven’t provided args to change the format behavior of indent. And I agree with Brett Cannon, you’d better adapt to space indent.

If you really want a try of that, you can find the black.py in site-packages folder and at the lines of 1540 in black.py change the ‘ ‘(four spaces) to ‘ ‘(a tab, copy a tab, and you can choose any spaces of the tab contains). Then you can get what you want. But, I really don’t recommend it.

Answered By: Steven-MSFT

Both autopep8 and black are very strict.
They don’t just recommend spaces over tabs, but force the usage of space indentation.

If you really want to use tabs, you should use yapf, with style use_tabs=True.

Answered By: Andre Goulart

Until maintainers/contributors add a setting to be able to indent Python with tabs, I found a workaround to this issue by using multi-command extension.

Steps to fix the issue:

  1. Install extension.

  2. Find your settings.json and keybindings.json. From here:

    Depending on your platform, the user settings file is located here:

     - Windows %APPDATA%CodeUsersettings.json
     - macOS $HOME/Library/Application Support/Code/User/settings.json
     - Linux $HOME/.config/Code/User/settings.json
    
  3. Add this to settings.json:

"multiCommand.commands": [
    {
        "command": "multiCommand.properlyFormatAnyDocument",
        "sequence": [
            "editor.action.formatDocument",
            "editor.action.indentationToTabs"
        ]
    }
]
  1. Add this to keybindings.json:
{
    "key": "shift+alt+f",
    "command": "extension.multiCommand.execute",
    "args": {
        "command": "multiCommand.properlyFormatAnyDocument"
    },
    "when": "editorTextFocus"
}
  1. Save all files and it works.

Technically, yapf has use_tabs setting, but I was never able to get it to work.

Answered By: wha7ever

So one of the comments was that yapf is not so easy to get working. Under Debian, install

apt-get install yapf3

Now go to your source directory and run

yapf3 --style "google" --style-help > .style.yapf

Edit the .style.yapf so that you put

use_tabs=True

instead of False.

Now run

yapf3 -i dirty.py

and it really use tabs for indentation. Spaces are still used for visual formatting and tabs only for real indentation, I am sending a visual example how my code is formatted.

enter image description here

Answered By: VojtaK

Pass in the argument --ignore=W191 to autopep8, and it would ignore the Indentation warning of indentation contains tabs.

For VSCode, use the settings-entry python.formatting.autopep8Args.
vscode-settings-entry-gui

Answered By: AgFlore