4

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.

Vlad the Impala
  • 15,572
  • 16
  • 81
  • 124
  • 9
    Should be community wiki. – gahooa Dec 10 '09 at 18:43
  • Are we talking about cross-platform portability, or about being able to package and distribute as an app/egg/whatever? – jcdyer Dec 10 '09 at 18:47
  • 2
    Can you provide one example of a "subtle 'gotcha'"? All the OS-specific stuff is clearly documented. Please show one thing that passes your test for "subtle". – S.Lott Dec 10 '09 at 18:53
  • 1
    The subject is too vague, you'll just end up with a bad digest of the Python doc modules which is very good as it is and easier to search. Maybe you should be more specific. In any case, has to be wiki. – RedGlyph Dec 10 '09 at 19:06
  • @S. Lott: I don't have the benefit of much experience, so they're all subtle to me. – Vlad the Impala Dec 10 '09 at 20:34
  • @Goose Bumper: Without an example, of "subtle" it's impossible to answer. If everything's "subtle" then you have to read the entire language and library manual because everything matters. – S.Lott Dec 10 '09 at 21:40
  • Do you want this question to include answers like "in the Transcrypt implementation of Python, if an exception is raised in the `else` of a `try-except-else-finally` block, the `finally` will not execute?" And do you want historical data, such as "in MicroPython up until version x.y.z, `raise(Exception('foo'), None)` did [...] instead of the normal Python behavior"? – mtraceur Mar 10 '20 at 09:36

7 Answers7

4

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.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
Baffe Boyois
  • 2,120
  • 15
  • 15
  • `array` could still be used with a conditional `.byteswap()` based on `sys.byteorder`, which is very fast. – RedGlyph Dec 11 '09 at 18:39
3

'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
  • 112,638
  • 29
  • 165
  • 179
2

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
  • 1,117
  • 7
  • 11
2

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
  • 21,433
  • 16
  • 79
  • 117
  • 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 Dec 12 '09 at 01:27
2

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.

Community
  • 1
  • 1
Jeff Bauer
  • 13,890
  • 9
  • 51
  • 73
1

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.

u0b34a0f6ae
  • 48,117
  • 14
  • 92
  • 101
Vlad the Impala
  • 15,572
  • 16
  • 81
  • 124
  • 11
    Or you can just use `/` on all platforms. – jcdyer Dec 10 '09 at 18:48
  • 1
    I don't think `os.pathsep` does what you think it does: `- os.pathsep is the component separator used in $PATH etc` – Chris Lutz Dec 10 '09 at 18:49
  • 2
    @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 `/`? – u0b34a0f6ae Dec 10 '09 at 18:53
  • 1
    @jcd: You've never encountered Windows utility that considers paths that starts with `'/'` as a command-line option: `'/help' != r'c:\help'`. – jfs Dec 10 '09 at 19:50
  • @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". – Vlad the Impala Dec 10 '09 at 20:50
  • @Goose: you first wrote `os.pathsep`, kaizer fixed it in the mean time. – RedGlyph Dec 11 '09 at 18:42
  • @Red: I see...sorry Chris, my mistake. Thanks kaizer :) – Vlad the Impala Dec 11 '09 at 21:00
1

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'
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 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). – u0b34a0f6ae Dec 11 '09 at 14:22
  • 1
    @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. – jfs Dec 11 '09 at 22:46