views:

291

answers:

7

I thought it would be a good idea to compile a list of things to watch out for when making a Python app portable. There are a lot of subtle 'gotchas' in portability that are only discovered through experience and thorough testing; there needs to be some sort of list addressing the more common ones.

Please post one gotcha (with its fix) per comment.

A: 

I'll start off:

Windows uses backslashes for path separators --> '\'

Unix uses forward slashes for path separators --> '/'

The os module comes with os.sep, which contains the path separator for the current platform that the script is being run on. Use os.sep instead of forward or back slashes. os.path.join will join two or more path components this way.

Goose Bumper
Or you can just use `/` on all platforms.
jcdyer
I don't think `os.pathsep` does what you think it does: `- os.pathsep is the component separator used in $PATH etc`
Chris Lutz
@jcd: Do you have a source for your statement? Consider more platforms than just Unix and Windows (like this answer). Also consider future not yet anticipated platforms. Which Python code will hold up better? Using `os.path.join` or using `/`?
kaizer.se
@jcd: You've never encountered Windows utility that considers paths that starts with `'/'` as a command-line option: `'/help' != r'c:\help'`.
J.F. Sebastian
@Chris: Here's what I have from 'Programming Python' page 107: "`os.sep` is whatever character is used to separate directory components on the platform on which Python is running".
Goose Bumper
@Goose: you first wrote `os.pathsep`, kaizer fixed it in the mean time.
RedGlyph
@Red: I see...sorry Chris, my mistake. Thanks kaizer :)
Goose Bumper
+3  A: 

'Universal newline support' (as descrived in PEP278) can come in handy for portability reasons.
It makes sure python code only gets \n:

christophe@orion:~$ printf 'testing pep278\r\n' > test.txt
christophe@orion:~$ python
Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> open('test.txt').read()
'testing pep278\r\n'
>>> open('test.txt','U').read()
'testing pep278\n'
ChristopheD
+2  A: 

Getting away from the syntax side of things, I think the biggest thing to watch out for is that typically when people think of python, they might not think of all the libraries it is composed of.

Many python packages depend on C libraries which may or may not be cross platform compatible. In addition, Python runs under Java through Jython, and .Net through IronPython. Unless libraries are written in pure python, they will not, in many cases, work on anything other than the C based version of python.

Bear
A: 

There are subtle differences in UCS2 and UCS4 (Windows and Linux, for example) builds of Python due to bugs, conflicting or deprecated standards, etc.

Example: Issue 3297

unicodetest.py:

#-*- coding: utf-8 -*-
print 'Result:', u'𐄣' == u'\U00010123'
print 'Len:', len(u'𐄣'), len(u'\U00010123')
print 'Repr:', repr(u'𐄣'), repr(u'\U00010123')

Output (Python 2.6, Linux):

Result: False
Len: 2 1
Repr: u'\ud800\udd23' u'\U00010123'
J.F. Sebastian
Is something missing on the Left-hand side(s), or should it really be `u''` (empty strings)? Also, the issue is not across Windows-Linux but Python builds configured narrow (any platform) and wide unicode (any platform).
kaizer.se
@kaizer.se: 1. There should be 'AEGEAN NUMBER TWO THOUSAND' character inside u'' http://www.fileformat.info/info/unicode/char/10123/index.htm 2. Technically you're correct you can *compile* python to use either representations, but technically you can *compile* python without unicode support too.
J.F. Sebastian
+2  A: 

If you deal with binary file formats in Python, note that the struct and array modules uses machine dependent size and endianness. struct can be used portably by always using < or > in the format string. array can't. It will probably be portable for arrays of bytes, but the documentation makes no such guarantee.

Baffe Boyois
`array` could still be used with a conditional `<array instance>.byteswap()` based on `sys.byteorder`, which is very fast.
RedGlyph
+1  A: 

Some modules are not cross-platform. Two that come to mind are both curses (Linux) and msvcrt (Windows). The fix to this simple problem is simply not to use them but find an alternative instead.

Noctis Skytower
In case anyone is interested, some googling does reveal an effort at a curses module for Python on Windows: http://github.com/adamv/wcurses
Nicholas Knight
A: 

Unix vs. Windows: Using Popen in the subprocess module will exhibit different behavior when shell=True. I won't offer a fix because the discussion is covered so well here, but it's one of those areas that can unexpectedly bite you.

Jeff Bauer