Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to suppress "unused variable" warnings in Eclipse/PyDev

How to suppress "unused variable" warnings in Eclipse/PyDev

When I'm working with functions that return tuples, I often only need one of the values, but still want to assign to multiple variables. I would like to be able to temporarily turn this warning off so I can zero in on more serious issues. Then, I can turn it back on when doing more of a final check.

If you're wondering why I would do this deliberately, it's just for readability. Say a function returns a tuple of tuples, several parts of my code might work with the third value like this:

label, content = myfunc()[2]

At times, I may only be interested in the 'content' piece, but I find this...

tmp, content = myfunc()[2]

...to be more parallel (and thus more readable) than this:

content = myfunc()[2][1]

If there's a better way to do this simply without assigning to a disposable unused variable, feel free to provide that as an answer.

>>> myfunc()[2]
('lab', 'val')
>>> , v = myfunc()[2]
SyntaxError: invalid syntax
>>> tmp, v = myfunc()[2]
>>> 
like image 865
Jon Coombs Avatar asked Dec 19 '12 01:12

Jon Coombs


4 Answers

If you don't need the value of a variable, assign it to the special variable _.

As far as Python is concerned, there is actually nothing special about _; it's just another legal identifier name like any other.

However, for most "lint"-style tools (hopefully including PyDev)—and, more importantly, human readers—it has the special meaning that "I don't need this variable, I'm only putting something here because the API/syntax/whatever requires it". Which means they won't warn you for not using it.

So:

_, content = myfunc()[2]

And yes, you are right that this is often more readable than myfunc()[2][1]. Not only that, but it helps you catch a few more errors—if myfunc()[2] doesn't have exactly two members, the tuple assignment will throw, but the [1] won't.

Very, very rarely, this is not a good idea because the value is something that you want to be garbage collected as soon as possible, and binding it to _ instead of just not binding it at all (e.g., via [2][1]) delays that.

More seriously, this does conflict with a different idiom that also makes special use of _: Code that uses gettext for internationalization typically does:

import gettext
_ = gettext.gettext

Or, equivalently:

from gettext import gettext as _

Obviously you can't use _ as both the gettext shortcut and the meaningless identifier. (You could actually get away with it, because the gettext meaning is bound at module-global level, and the meaningless identifier should only be used inside function bodies… but still, it's a very bad idea to try, because at some point you will end up using the gettext _ in a function after you've assigned a local value that shadows it.) Nothing's forcing you to use _ in either case—but if you use anything else, you are likely to confuse readers (and possibly the same linting tool you're looking to pacify in the first place). So, you have to decide which one is more important to you in any given project. (And usually, if you're using gettext, that's going to be the more important one.)

If you're repeatedly calling myfunc and disposing of some of the values, you might want to consider writing a wrapper function:

def mywrapperfunc():
    _, content = myfunc()[2]
    return content

Then your code can just do:

content = mywrapperfunc()

This has a number of advantages:

  • It's obviously easier to read than anything that requires you to remember that you want the second half of a tuple which is in index 2 of the sequence that's returned by myfunc.
  • It gives you a place to put a nice name (hopefully nicer than mywrapperfunc) and/or comments/docstrings, in case it isn't trivial.
  • It means that if you later change myfunc so the value you want is now in index 3 instead of 2, and the second member of a 3-element tuple instead of a 2-element tuple, you only need to change mywrapperfunc instead of 20 different lines of code.
  • It also means that if you later want to use a conflicting _ idiom (e.g., to i18n your code with gettext), you only need to change it in one place.

One side note: In the interactive interpreter, _ does have a special meaning: it's bound to the result of the last interactive command. But that doesn't mean you can't use _ in the interactive interpreter. (In fact, it's even better there, because anything you stash there is immediately overwritten, so the very rare GC problem doesn't come up.)

like image 131
abarnert Avatar answered Nov 15 '22 00:11

abarnert


Add the comment #@UnusedVariable to the end of the line.

Every warning in PyDev has a similar deactivation comment. Use Quick Fix to discover them (place the cursor in the warning and press Ctrl+1), or refer to these lines from the PyDev source code:

public static final String MSG_TO_IGNORE_TYPE_UNUSED_IMPORT = "@UnusedImport";
public static final String MSG_TO_IGNORE_TYPE_UNUSED_WILD_IMPORT = "@UnusedWildImport";
public static final String MSG_TO_IGNORE_TYPE_UNUSED_VARIABLE = "@UnusedVariable";
public static final String MSG_TO_IGNORE_TYPE_UNDEFINED_VARIABLE = "@UndefinedVariable";
public static final String MSG_TO_IGNORE_TYPE_DUPLICATED_SIGNATURE = "@DuplicatedSignature";
public static final String MSG_TO_IGNORE_TYPE_REIMPORT = "@Reimport";
public static final String MSG_TO_IGNORE_TYPE_UNRESOLVED_IMPORT = "@UnresolvedImport";
public static final String MSG_TO_IGNORE_TYPE_NO_SELF = "@NoSelf";
public static final String MSG_TO_IGNORE_TYPE_UNDEFINED_IMPORT_VARIABLE = "@UndefinedVariable";
public static final String MSG_TO_IGNORE_TYPE_UNUSED_PARAMETER = "@UnusedVariable";
public static final String MSG_TO_IGNORE_TYPE_NO_EFFECT_STMT = "@NoEffect";
public static final String MSG_TO_IGNORE_TYPE_INDENTATION_PROBLEM = "@IndentOk";
public static final String MSG_TO_IGNORE_TYPE_ASSIGNMENT_TO_BUILT_IN_SYMBOL = "@ReservedAssignment";
public static final String MSG_TO_IGNORE_TYPE_PEP8 = "@IgnorePep8";
public static final String MSG_TO_IGNORE_TYPE_ARGUMENTS_MISATCH = "@ArgumentMismatch";
like image 34
joshua Avatar answered Nov 14 '22 23:11

joshua


Preferences -> PyDev -> Editor -> Code Analysis , "Unused" tab

Find the setting the for

Don't report unused variable if name starts with: (comma separated)

and then use one of the prefixes on this list, or add another prefix.

For example, if you have a throwaway variable "tmp" in the following code:

tmp, content = myfunc()[2]

and you have '_' on your list of prefixes to ignore, then convert "tmp" to "_tmp" like this:

_tmp, content = myfunc()[2]

Your error will go away. I think this is a more readable solution than just using '_', as suggested by @abarnert, and it also avoids the complications of conflicting with translation.

like image 43
Mark Chackerian Avatar answered Nov 15 '22 00:11

Mark Chackerian


I run into this some times when I use a feature similar to the one you describe when a tuple is returned. You can globally set warning levels for the code analysis of PyDev in the Preferences -> PyDev -> Editor -> Code Analysis section. In Code Analysis in the Unused tab, there is an option to set the warning level for "Unused variable" as well as other occurrences.

like image 43
sid16rgt Avatar answered Nov 14 '22 23:11

sid16rgt