Syntax suggestion for imports
The standard library, my personal code, third-party packages, and my employer's code base are filled with examples of the following pattern: try: import threading except ImportError: import dummy_threading as threading try: import xml.etree.cElementTree as ET except ImportError: try: import cElementTree as ET except ImportError: import elementtree.ElementTree as ET try: from cStringIO import StringIO except ImportError: from StringIO import StringIO try: import readline except ImportError: pass How about a new, simpler syntax: * import threading or dummy_threading as threading * import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET * from cStringIO or StringIO import StringIO * import readline or emptymodule
Raymond Hettinger wrote:
How about a new, simpler syntax:
* import threading or dummy_threading as threading * import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET * from cStringIO or StringIO import StringIO
These all look good to me. The "short circuit" import syntax and semantics are compact and intuitive.
* import readline or emptymodule
This I find more problematic as "emptymodule" seems too magical. Even now any code that wants to use a module that might not have been successfully imported needs to check if that's the case. E.g., a fuller current use-case would be: try: readline = None import readline except ImportError: pass if readline is not None: readline.foo() ... Conceivably emptymodule could act as a Null object but that could create more problems than it solves. John
I wonder if your perceived need for this isn't skewed by your working within the core? Also, in 3.0 many of the use cases should go away -- e.g. cStringIO vs, StringIO, etc., as we switch the stdlib to having a single "public" name for an API which automatically replaces or augments itself with the accelerated C version if available. --Guido On Jan 2, 2008 5:19 PM, Raymond Hettinger <python@rcn.com> wrote:
The standard library, my personal code, third-party packages, and my employer's code base are filled with examples of the following pattern:
try: import threading except ImportError: import dummy_threading as threading
try: import xml.etree.cElementTree as ET except ImportError: try: import cElementTree as ET except ImportError: import elementtree.ElementTree as ET
try: from cStringIO import StringIO except ImportError: from StringIO import StringIO
try: import readline except ImportError: pass
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/guido%40python.org
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
On Wed, Jan 02, 2008, Raymond Hettinger wrote:
The standard library, my personal code, third-party packages, and my employer's code base are filled with examples of the following pattern:
try: import threading except ImportError: import dummy_threading as threading
How about a new, simpler syntax:
* import threading or dummy_threading as threading
My gut reaction is -0. For starters, many of these should go away with Python 3.0 (e.g. cStringIO). Also, annoying as the try/except is, I think the fact that it signals the special import is helpful; your suggestion is too light-weight IMO. If you could devise something just a bit heavier, that would be much better. -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Weinberg's Second Law: If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Jan 2, 2008, at 9:08 PM, Aahz wrote:
On Wed, Jan 02, 2008, Raymond Hettinger wrote:
The standard library, my personal code, third-party packages, and my employer's code base are filled with examples of the following pattern:
try: import threading except ImportError: import dummy_threading as threading
How about a new, simpler syntax:
* import threading or dummy_threading as threading
My gut reaction is -0. For starters, many of these should go away with Python 3.0 (e.g. cStringIO). Also, annoying as the try/except is, I think the fact that it signals the special import is helpful; your suggestion is too light-weight IMO. If you could devise something just a bit heavier, that would be much better.
I tend to agree. The little bit of syntactic sugar doesn't really seem worth it. - -Barry -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (Darwin) iQCVAwUBR3xT9nEjvBPtnXfVAQIX/QQAmg9RczTAxHUe3qsry3F9DcUQZX32C9HS VMETbSnoVS0Xrdm5J7cCYqjpHlPXLKRoFCuYGWJ03ivjws/DzAsTXhpFwSmISZId 43W2UCC6mX8izr3E+bC4uEagw7EiVFsDEIX52FoUx6vIig0piZq3XolpQUqk4tP2 EhxQzTZwx6c= =U9qz -----END PGP SIGNATURE-----
On Jan 2, 2008 7:19 PM, Raymond Hettinger <python@rcn.com> wrote:
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule
I'm sympathetic to this syntax proposal, as I find the repetition and extra lines for a simple idea to be a little unpleasant. This would also allow us to decide whether the import 'or' handling would be triggered equivalently to the except ImportError case you described, or only for missing imports. The latter would stop errors in existing modules from being silenced (and may give reason to allow emptymodule or None), but I'm unsure if that's a good thing. Of the above I find the ElementTree migration to be the most compelling, yet it seems ill-timed to bring syntax into Python 2.x you'd be unable to use until you no longer needed it. However your later example of the PageTemplateFile, which appears to be due to a third-party module reorganization and could certainly happen during the lifetime of late 2.x, helps swing me back the other way. -- Michael Urman
Raymond Hettinger wrote:
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule
The syntax idea has a nice ring to it, except for the last idea. As others have already said, the name emptymodule is too magic. The readline example becomes more readable when you change the import to import readline or None as readline In my opinion the import or as syntax definition is easy to understand if you force the user to always have an "as" statement. The None name is optional but must be the last name: import name[, or name2[, or name3 ...] [, or None] as target This translates into: try: import name as target except ImportError: try: import name2 as target except ImportError: target = None from name[, or name2 ...] [, or None] import target translates into try: from name import target except ImportError: try: from name2 import target except ImportError: target = None Christian
At 3:20 PM +0100 1/3/08, Christian Heimes wrote:
Raymond Hettinger wrote:
How about a new, simpler syntax: ... * import readline or emptymodule
The syntax idea has a nice ring to it, except for the last idea. As others have already said, the name emptymodule is too magic.
The readline example becomes more readable when you change the import to
import readline or None as readline
In my opinion the import or as syntax definition is easy to understand if you force the user to always have an "as" statement. The None name is optional but must be the last name:
import name[, or name2[, or name3 ...] [, or None] as target ...
At 11:48 AM -0600 1/3/08, Ron Adam wrote: ...
An alternative possibility might be, rather than "or", reuse "else" before import. ...
I prefer "else" to "or" but with the original single-statement syntax. If the last clause could be an expression as well as a module name, what I've done (used with and copied from BeautifulSoup): try: from htmlentitydefs import name2codepoint except ImportError: name2codepoint = {} could become: from htmlentitydefs else ({}) import name2codepoint as name2codepoint Also: import foo or (None) as foo -- ____________________________________________________________________ TonyN.:' <mailto:tonynelson@georgeanelson.com> ' <http://www.georgeanelson.com/>
On 3 jan 2008, at 02.19, Raymond Hettinger wrote:
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule
Wouldn't a (stdlib) function suffice in the cases where this is needed? ET = import_with_alternative("xml.etree.CElementTree", "cElementTree", "elementtree.ElementTree") It's not as elegant, but it's easier than status quo. //Simon
Simon Percivall wrote:
Wouldn't a (stdlib) function suffice in the cases where this is needed?
ET = import_with_alternative("xml.etree.CElementTree", "cElementTree", "elementtree.ElementTree")
It's not as elegant, but it's easier than status quo.
I like that direction a lot better than the syntax proposals. This isn't the kind of thing that needs to get composed into bigger expressions, which is where clever uses of operators really shine. Here, I think the operators were subtracting clarity and your named function was adding clarity. When I saw the OP, I actually wondered why people whose codebases are "filled" with the same try/except block over and over hadn't just written their own import_with_alternative function in the first place. If I wanted half my lines of code to be devoted to control flow and block structure, I'd write in one of those curly-brace languages :)
[Half tongue-in-cheek] -On [20080104 08:04], Drew Perttula (drewp@bigasterisk.com) wrote:
When I saw the OP, I actually wondered why people whose codebases are "filled" with the same try/except block over and over hadn't just written their own import_with_alternative function in the first place.
Because you would have to import it as well in order to use it? ;) -- Jeroen Ruigrok van der Werven <asmodai(-at-)in-nomine.org> / asmodai イェルーン ラウフロック ヴァン デル ウェルヴェン http://www.in-nomine.org/ | http://www.rangaku.org/ Taxation without representation is tyranny...
Jeroen Ruigrok van der Werven wrote:
[Half tongue-in-cheek]
-On [20080104 08:04], Drew Perttula (drewp@bigasterisk.com) wrote:
When I saw the OP, I actually wondered why people whose codebases are "filled" with the same try/except block over and over hadn't just written their own import_with_alternative function in the first place.
Because you would have to import it as well in order to use it? ;)
The keyphrase was "people whose codebases are 'filled' with ..." If they are maintaining a codebase, then I am sure adding one utility function to their library would be trivial. Or if you have enough of them in one file.. dedicating 7 lines of code for: def import_any(*names): for name in names: try: return __import__(name) except StandardError: pass raise ImportError('no importable names') , seems like a bargain for readability. Or to include the "None" case that people have brought up, we can spare 2 more lines: def import_any(*names, **kwargs): required = kwargs.get('required', True) for name in names: try: return __import__(name) except StandardError: pass if required: raise ImportError('no importable names') If nothing else, writing this email will remind me to avoid this try/except pattern in future codebases, if I have more than 1 instance of it (right about the break even point). -Scott -- Scott Dial scott@scottdial.com scodial@cs.indiana.edu
Raymond Hettinger wrote:
The standard library, my personal code, third-party packages, and my employer's code base are filled with examples of the following pattern:
try: import threading except ImportError: import dummy_threading as threading
try: import xml.etree.cElementTree as ET except ImportError: try: import cElementTree as ET except ImportError: import elementtree.ElementTree as ET
try: from cStringIO import StringIO except ImportError: from StringIO import StringIO
try: import readline except ImportError: pass
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule
I don't think it's as visually clear, but that may be I'm just not used to it. An alternative possibility might be, rather than "or", reuse "else" before import. import threading else import dummy_threading as threading import xml.etree.CElementTree as ET else import cElementTree as ET else import elementtree.ElementTree as ET The readline example above should be in a try except as it allows a failure to pass. For example if you wanted to allow the above elementtree example to pass instead of raising an exception you would write.. try: import xml.etree.CElementTree as ET else import cElementTree as ET else import elementtree.ElementTree as ET except ImportError: pass # or handle failed import. This still improves readability and flattens out the multiple nested structure which I believe is what makes the current way unappealing. I think multiple possible imports in "from - import"s statements should not be allowed. When you consider multiple imports from possibly multiple sources, it seems like that could get a bit messy when debugging. Regards, Ron
2008/1/2, Raymond Hettinger <python@rcn.com>:
How about a new, simpler syntax:
* import threading or dummy_threading as threading
* import xml.etree.CElementTree or cElementTree or elementree.ElementTree as ET
* from cStringIO or StringIO import StringIO
* import readline or emptymodule
With the minor modification of changing emptymodule by a None in the last line, I'm +0 on it. I don't use this that much, but I find this syntax clear and understable. It does not bring additional complexity when not used, and is very helpful when needed. Don't know how much effort for the parser it is, though. Regards, -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org/ar/
participants (14)
-
Aahz -
Barry Warsaw -
Christian Heimes -
Drew Perttula -
Facundo Batista -
Guido van Rossum -
Jeroen Ruigrok van der Werven -
John Barham -
Michael Urman -
Raymond Hettinger -
Ron Adam -
Scott Dial -
Simon Percivall -
Tony Nelson