I'm trying to figure out what the options -t and -tt do.
From the doc:
Issue a warning when a source file mixes tabs and spaces for indentation in a way that makes it depend on the worth of a tab expressed in spaces. Issue an error when the option is given twice (-tt).
I'm not getting it, in particular the bolded sentence, what does it mean? A tab is a tab ('\t') a space is a space (' ') and in ascii table they also have 2 different codes.
I'll ty to make an example to explain better myself. I code:
if True:
print('hello') # here a tab that my editor represents with 4 spaces
print('world') # here just used 4 spaces
Now this code, I tried, doesn't work neither in Python3 nor in Python2, so what does -t do?
Could you give me a clarification?
When used as indentation, tabs must be interpreted as equivalent to a number of spaces. How many spaces depends on how you configured your editor, and how many spaces preceded the tab on the same line. That's because tabs represent a jump to the next tabstop. If you used 2 spaces plus a tab, you have signalled a jump to column 8, as if you inserted 6 spaces.
In addition, some people set their tabstops to be the equivalent of 4 spaces, others set it to be the same as 8 spaces. These people then use tabs in indentation in different ways too. You could use 4 spaces for one indentation level, then use tabs at 8 spaces for the next, then use a tab plus 4 spaces, etc. Or you could use tabs for all indentation levels, having set the tab size to represent 4 spaces.
Python needs to handle mixing of tabs and spaces, and then hope that you used it consistently; e.g. you didn't use 4 spaces first, then a tab to indent to what you thought was an indentation equivalent to 12 spaces. Python can easily get this wrong when you are inconsistent.
The -t and -tt options point out where you may have gotten this wrong by doing more rigorous and thorough testing of all lines.
The ease by which you can produce confusing results, between various tab sizes and mixing tabs and spaces, is the reason why the Python Style Guide (PEP 8) strongly recommends that you use spaces only:
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
In Python 3, mixing tabs and spaces for indentation is now an error.
To be precise: Python starts out assuming you used 8 spaces for a tab. See the Indentation documentation, part of the Lexical Analysis specification:
First, tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight (this is intended to be the same rule as used by Unix). The total number of spaces preceding the first non-blank character then determines the line’s indentation. Indentation cannot be split over multiple physical lines using backslashes; the whitespace up to the first backslash determines the indentation.
Python 2 also looks for Emacs and VI-style configuration comments; if the tokenizer finds a comment with tab-width:, :tabstop=, :ts= or set tabsize= in it, followed by digits, like:
# -*- tab-width: 4 -*- (emacs)
# :tabstop=4 (vi)
or similar variants, then Python sets the tabsize from that. This support was removed from Python 3.
If you then mix tabs and spaces that may be inconsistent, and use -t, the text <filename>: inconsistent use of tabs and spaces in indentation is written to sys.stderr once for that file. If you used -tt, a TabError exception is raised instead.
The error will be thrown when a source file depends on tabs expanding to a certain number of spaces.
For example, a file like this would be problematic:
def function():
print 'hello'
\tprint 'goodbye'
The above code would work if a tab was 4 spaces, but would fail if it was anything else (except 0, which is nonsensical).
The -t option attempts to highlight such issues.
Related
I am using PyCharm IDE for python coding. I prefer to use tabs over spaces for indentation. I've changed the setting accordingly in python. Also, since Python gives a warning if a line exceeds 120 characters, I've added hard-wrap also. Now, if some line exceeds 120 characters, when I do code-reformat, PyCharm moves it to next line which is absolutely fine. But what it does while moving it to next line is it adds a mixture of tabs and spaces in the indentation.
To be a bit more specific, suppose the code is at an indentation level of 3 tabs and the line exceeds 120 character limit. So, while reformatting, it moves a part of the code to next line. This line has indentation consisting of 6 tabs and 2 spaces. Now, again PyCharm gives a warning that indentation is mixture of tabs and spaces.
How to solve this problem?
I know I can ignore that warning or disable 120 character limit or use spaces instead of tabs. But I don't want to do them. I'm used to those settings. I want to know how to fix PyCharm so that it uses only tabs and no spaces.
Thank you!
The question is how to properly break lines according to PEP8 while using TABs.
So here is a related question How to break a line in a function definition in Python according to PEP8. But the issue is that this only works properly when the length of the definition header def dummy( is an integer multiple of the tab length.
def tes(para1=x,
--->--->para2=y)
Otherwise I end up with a new error and flake8 complains about Error E127 or E128 because the its either over- or under-indented like this:
Under-indented E128
def test(para1=x,
--->--->para2=y)
Over-indented
def te(para1=x,
--->--->para2=y)
A solution where flake8 does not complain is to do:
def test(
--->--->para1=x,
--->--->para2=y
--->--->)
However, when I am programming I don't necessarily know in advance how many parameters I'm gonna use in that test() function. So once I hit the line limit I have rearrange quite a bit.
This obviously does apply to all continuations. Does this mean the cleanest solution is to break the line as soon as possible for every line which final length cannot be said by the time of first writing, or is there another solution.
Tab and space shall not be mixed for the solution.
So now I ask myself what is the legis artis to deal with line continuations?
I'm turning my original comment into an official answer.
The PEP-0008 has a section about whether to use Tabs or Spaces, quoted below (with my emphasis):
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is
already indented with tabs.
Python 3 disallows mixing the use of tabs and spaces for indentation.
Python 2 code indented with a mixture of tabs and spaces should be
converted to using spaces exclusively.
When invoking the Python 2 command line interpreter with the -t
option, it issues warnings about code that illegally mixes tabs and
spaces. When using -tt these warnings become errors. These options are
highly recommended!
You're running into issues with tabs, and you don't say whether you're using Python2 or 3, but I'd suggest you stick to the PEP-0008 guidelines.
You should replace tab chars in the file/module with 4 spaces and use spaces exclusively when indenting.
WARNING: Be very careful if you plan to use shell commands to do this for you, as some commands can be dangerous and mangle intended tab chars within strings (i.e. not only indentation tabs) and can break other things, such as repositories -especially if the command is recursive.
PEP8 is very clear:
Tabs or Spaces?
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
Python 3 disallows [emphasis added] mixing the use of tabs and spaces for indentation.
Reference: python.org.
So if you're writing new code and want to adhere to standards, just use spaces.
This question already has answers here:
I'm getting an IndentationError. How do I fix it?
(6 answers)
Closed last month.
The following python code throws this error message, and I can't tell why, my tabs seem to be in line:
File "test.py", line 12
pass
^
TabError: inconsistent use of tabs and spaces in indentation
class eightPuzzle(StateSpace):
StateSpace.n = 0
def __init__(self, action, gval, state, parent = None):
StateSpace.__init__(self, action, gval, parent)
self.state = state
def successors(self) :
pass
You cannot mix tabs and spaces, according the PEP8 styleguide:
Spaces are the preferred indentation method.
Tabs should be used solely to remain consistent with code that is already indented with tabs.
Python 3 disallows mixing the use of tabs and spaces for indentation.
Python 2 code indented with a mixture of tabs and spaces should be converted to using spaces exclusively.
When invoking the Python 2 command line interpreter with the -t option, it issues warnings about code that illegally mixes tabs and spaces. When using -tt these warnings become errors. These options are highly recommended!
Using Visual Studio 2019
I was using tabs but the editor was inserting spaces and it would result in errors.
To avoid getting the spaces and tabs mixed up , set your preferences
Go to Edit->Advanced->Set Leading Whitespace->Tabs (or Whitespaces)
After I set it to Tabs, my tabs stop being represented as spaces and it worked fine thereafter
For linux nano users:
if your code includes 4 spaces instead of a tab, you should keep using 4 spaces or change all of them to a tab. If you use mixed it gives an error.
open your code in a text editor, highlight all of it (ctr+a) and go to format and select either "Tabify region" or "Untabify region". It'll just make all the indents have the same format.
not using the backspace also is important (especially in the Leafpad editor). If you want to decrease indent, use only Alt_key + TAB.
This should be done when you delete a line in a Python code.
I have tried using a function defined using subprocess but I get an indentation error depending on where I put it on my code. A minimal example of my code is:
import subprocess
def runsafe(job,args):
jobs=[job];
for arg in args:
jobs.append(arg)
proc=subprocess.Popen(jobs,stdout=subprocess.PIPE)
return proc.stdout.readlines()
if __name__=="__main__":
runsafe("mkdir","Try")
A=0
B=7
This works and gives me the correct input (this code just creates three new folders called T, r, y where it's executed) but the indentation seems weird to me. A and B are just two constants that I will use later in the code.
For me the most natural would be to write:
import subprocess
def runsafe(job,args):
jobs=[job];
for arg in args:
jobs.append(arg)
proc=subprocess.Popen(jobs,stdout=subprocess.PIPE)
return proc.stdout.readlines()
if __name__=="__main__":
runsafe("mkdir","Try")
A=0
B=7
If I do this I just get:
IndentationError: 'unexpected indent'
Why is it necessary to indent (again) the line where I call runsafe? Shouldn't it work if I use it like in the second example?
You are very likely mixing tabs and spaces in your indentation. With Python 2 this often leads to weird behavior because mixing tabs and spaces actually works. But it doesn’t work in the way you would maybe expect: For Python 2, a tab is equivalent to 8 spaces. So for evaluating the indentation level, every tab is replaced by 8 spaces.
So when you have an indentation like this (where a . is a space, and ---→ is a tab):
def test():
........pass
---→pass
then it might look weird but it is valid since everything is indented using 8 spaces.
So you should make sure that you are using consistent indentation (it doesn’t matter whether it’s spaces or tabs—as long as it’s consistent).
Btw.: In Python 3 this is no longer allowed and will throw a syntax error (actually a TabError) with an actually helpful message: TabError: inconsistent use of tabs and spaces in indentation.
Your code mixes tabs and spaces for indentation. While this was possible and allowed in Python 2, Python 2 assumes tab size of 8 spaces. If you had an editor that has a setting to turn on visible whitespace, you'd see that one of the lines is indented with 8 spaces, and the other 2 with a single TAB:
if __name__=="__main__":
........runsafe("mkdir","Try")
--->A=0
--->B=7
That is, in your editor you had the tab display default to 4 spaces, while Python 2 expects 8 spaces to match a TAB.
As the tab size cannot be agreed on, yet in Python the indentation is significant, use of tabs for indentation is not considered best practice in either Python 2 or Python 3.
Tabs should be used solely to remain consistent with code that is already indented with tabs:
And mixing tabs and spaces in a way that makes indentation depend on the worth of a tab expressed in spaces is very wrong.
In Python 2 the tab size is 8, so indentation of TAB counts the same as 8 spaces or single TAB. Unfortunately there are many code editors that do not realize this, and instead use a different tab size for Python 2 code. In Python 3 OTOH, a TAB is only matched by another TAB. A good Python 3 editor would then mark inconsistent use of tabs in indent as syntax errors.
Thus the only consistent way of using tabs is using only tabs for indentation. In Python 2 there is a switch for that; you can start your Python interpreter with option -tt, or put it on the #! line after the python command, which will cause Python 2 to throw an error if it ever meets a line which makes the indent depend on tab size.
However, if you're writing new code, please be advised that the Python community almost uniformly follows the PEP 8 coding conventions: indentations are 4 spaces, and no tabs are used. In my experience, it is only the ever so odd legacy project that does not obey this guideline. Nearly all open-source projects these days that have coding conventions also require 4-space indentation, as well as other aspects of PEP 8.
I'm editing a file that was initially written in emacs and that I am now working on in vim. I've been running into an odd problem when switching from one to the other:
At some places in the code, seemingly randomly, there are tabs in the emacs code that are equivalent to two tabs (both visually in emacs and in python). However, in vim these tab characters show up as only a single tab.
When I :set list, an example few lines will show up as:
for i in range(total_pairs):$
^Iwhile 1:$
^I rint = random.randint(0,total_pairs-1)$
^I if(trialData[rint].cueDir == FORWARD)$
^I^ItrialData[rint].cueDir=BACKWARD$
^I^Ibreak$
While it should appear as:
for i in range(total_pairs):$
while 1:$
rint = random.randint(0,total_pairs-1)$
if(trialData[rint].cueDir == FORWARD):$
trialData[rint].cueDir = BACKWARD$
break$
The code still runs either way, but it's fairly annoying to read.
When I run :retab, it replaces each ^I with one tab, instead of the two tabs that it should. What can I do to replace each ^I character with two tabs instead of one. Also, why is this happening?
Thanks.
The easy, (and recommended), answer is replace each tab with 4 spaces and set both emacs and vim to use 4 spaces when tab is pressed.
When I run :retab, it replaces each ^I with one tab, instead of the two tabs that it should.
:retab replaces each tab character (i.e. ^I) with tabstop spaces. In your case, tabstop is evidently set to 4, so Vim replaces each ^I in the file with 4 spaces. If you expect :retab to replace each ^I with 8 spaces, use set tabstop=8 before :retab.
To address the actual problem, do not use mixed indentation in Python; set up both Emacs and Vim to use spaces for tabs.
See :h expandtab, :h tabstop, :h softtabstop, and :h shiftwidth for more information.