One of my projects uses shlex.quote
which is available since python 3.3. But that shlex.quote
is the same as pipes.quote
which is deprecated after moving to shlex.
Now for compatibility I am using this code:
def cmd_quote(string):
import sys
if int(sys.version[2]) < 3:
import pipes
return pipes.quote(string)
else:
import shlex
return shlex.quote(string)
Are any better practices exists?
First, if you want to do numerical comparisons against version, use version_info
, don't try to parse the string in version
.*
This also means you can take advantage of the way tuples are compared and write code like:
if sys.version_info < (3, 3):
… and it won't break if Python gets to 3.10.0 or 4.0 ever come out.
* Unless you need to worry about 1.5 vs. 2.0, in which case you've obviously got a time-machine gatewaying between Usenet and StackOverflow, and surely you can think of better uses for that.
Anyway, it's probably better to just test for shlex.quote
existing in the first place. That way, it's obvious to the reader what you're doing: using shlex.quote
if possible, falling back to pipes.quote
if not.
You'll see that pattern all over the place—even in the stdlib, where code is imported from C accelerator modules if possible, but fallback code is used if not (e.g., if you're using PyPy instead of CPython).
Also, note that pipes.quote
is only documented in 2.7. Not 3.0-3.2 (which is what it seems like you care about…), or 2.6, or any other version. You're relying on something that happens to be there in a particular implementation. (Well, practically, in all of them,* but still, why rely on that if you don't have to?)
* As far as I know, there aren't any 3.2 implementations that have pipes
and shlex
but don't have pipes.quote
. And there probably won't be too many new 3.2 implementations created in the future.
Also, while it can occasionally be useful to import
in the middle of a function, it's kind of a weird thing to do. If there's a problem with the installation on a machine you deploy this on, would you really expect to be able to import your module successfully, but then later get an ImportError
on calling some function? That's the kind of thing people get baffled by and run to SO for help with all the time. :) (It's also obviously a bit of a performance hit to do all this looking in sys.modules
and converting strings to ints and so on when you don't need to, but I doubt that's going to matter.)
So, I think the way I'd write it would be:
try:
from shlex import quote as cmd_quote
except ImportError:
from pipes import quote as cmd_quote
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With