开发者

Python * imports

开发者 https://www.devze.com 2023-03-02 20:34 出处:网络
I\'ve generally been told that the following is bad practice. from module import * The main reasoning (or so I\'ve been told), is that you could possibly import something you didn\'t want, and it c

I've generally been told that the following is bad practice.

from module import *

The main reasoning (or so I've been told), is that you could possibly import something you didn't want, and it could shadow a similarly named function or class from another module.

However, what about PyQt

from PyQt4.QtCore import *

Every example I've ever seen is written this way, mainly because everything exported from Qt starts with "Q", so it's not going to shadow anything.

What's the concensus? Is it always bad to use * imports?

EDIT:

Just to be clear, this question is specifically in regards to using PyQt4. It has nothing to do with the way I am designing some other project.

Basically, I've found that coding to PEP8 has improved my code readability, except with regards to importing PyQt4, and so I've disregarded the frowns from purists until now. But now my dev group is deciding on one convention and I'm wondering if this is a scenario "where practicality beats purity", or if I should just suck it up and deal with monstr开发者_如何学JAVAous PyQt4 imports

from PyQt4.QtGui import QComboBox, QLineEdit, QLayout, Q;lakdfaf.......


This can sort of turn into a religious war. It's a matter of whether you want to be explicit or whether you want to avoid being too verbose. In general, following the Zen of Python, it's better to be explicit, but sometimes people just don't find it practical to list every import from particular module.


My general rule is that if I didn't write the module, I don't import it all. My biggest fear is actually over writing local variables that might have been defined in the imported module. So to keep from having to type in long module names, I use the import as feature. Using your module as an example I would do the following:

import PyQt4.QtCore as qt

That being said, I have many support modules that I write that I will import everything. Like the pyqt module, I name them with a descriptive name that helps show which module it came from.

Edit per comment
When I use import*, my support modules do not contain classes or anything that can create a new instance. They tend to be groups of functions that modify existing instances only. To help clarify my opinion: If I am the owner of the source code and I will be the primary maintainer, I will use the import* otherwise I would use the import as.

Another reason that I use the import as feature is to allow me to mock modules for debugging purposes. In a project that I am working on now, I use pyVisa to talk to a number of GPIB devices. When I'm not connected to the devices GPIB network, I can use a dummy_visa module to write to the stdout(to verify I am sending the correct format) and return a random number (to test my application). See below

if visa_debug:
    import dummy_visa as visa
else:
    import visa
gpib = visa.Instrument("GPIB0::10")
gpib.write("MEAS:VOLT?")


Making an explicit exception for modules that already include a namespace in their naming convention (such as the Q* of PyQT) is perfectly reasonably. However, I recommend being clear that the default is still "don't use it" and simply list this exception in your coding guidelines.

import * is also acceptable when it is used as a namespace manipulation trick within an application (the two forms of that I am familiar with are optional C acceleration modules that are imported at the end of the pure Python version, and "flattening" a package namespace in __init__). The key point is that the importing module and the module being imported are under the control of the same set of developers, and hence avoiding namespace clashes is completely within their control.

The final exception is for convenience at the interactive prompt.

In other situations, it is best to either import specific names or reference them indirectly through the module name (or, if there are some commonly reference items, do both:

import module # Can access anything from module import a, b, c # But we reference these a lot, so retrieve them directly


Tutorial, chapter 6:

Note that in general the practice of importing * from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions.

Tutorial, chapter 10:

Be sure to use the import os style instead of from os import *. This will keep os.open() from shadowing the built-in open() function which operates much differently.

So it seems that it is definitely a bad idea sometimes; not-the-best idea most of the time; and an acceptable shortcut in cases where you'd want to type less, eg in interactive sessions.


I find import * gets abused, and can become a maintenance headache, so I avoid it for this and the other reasons you state. That said I feel it's okay for short interactive sessions, e.g. from pylab import *.

In production code, for packages like PyQt4.QtCore where you plan to use many of the symbols, I'd use one of the following syntaxes which make it explicit which namespace the symbols come from:

from PyQt4 import QtCore
# explicit where the symbol came from
QtCore.QTime()

import PyQt4.QtCore as QT
# less desirable since you need to look in the header to find out what QT is
# but I still prefer it to import *
QT.QTime()


In general, if you're going to use from X import Y, it's a good idea to be explicit about what you're importing. That's not just because it's safer, but also because it makes your code more readable (and upgrades to the third-party modules you're using won't have as much potential to incidentally break your code).

In some code examples demonstrating big packages, like Qt or matplotlib, the examples will use from module import * because they're often only importing from one module, and it saves typing and lets their example code get to the point. There's no reason you can't do it in your code, but at least use it in moderation, especially if it's in big source files or other people will be looking at your code.


The PyQt design is water under the bridge. I'm not sure it's the best thing, but it's probably influenced by the way Qt was designed. AFAIK, Qt didn't use C++ namespaces historically (I'm not sure if it uses them now), and therefore had to use prefixes. But all of those design decisions probably happened more than 10 years ago, and that shouldn't affect your design decisions now.

I know that if I was designing a library now, I would definitely choose to use package namespaces (which you would import explicitly in Python) over prefixes. Let's say my prefix is Pfx - if the library user doesn't care writing PfxFunc() every time he needs a function, he certainly wouldn't care about the extra character in Pfx.Func(), especially when he can use import with specific symbol names to shorten that even more.


Consider this case

from foo import *
from bar import *

x=baz()

Now suppose foo has a function called baz() that we are using in our code and everything is working fine. Months or years pass, the author of bar adds a function called baz(). Someone updates the egg ang bingo - we have a potentially hard to detect bug in the program.

Not to mention that just looking at those three lines of code, I can't tell where baz comes from without going and looking at foo and bar

The only time I'd use import * would be in the interpreter to save some typing

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号