Search code examples
pythonposixcarriage-returnlinefeednt

'\n' == 'posix' , '\r\n' == 'nt' (python) is that correct?


I'm writing a python(2.7) script that writes a file and has to run on linux, windows and maybe osx. Unfortunately for compatibility problems I have to use carriage return and line feed in windows style. Is that ok if I assume:

str = someFunc.returnA_longText()
with open('file','w') as f:
    if os.name == 'posix':
        f.write(str.replace('\n','\r\n'))
    elif os.name == 'nt'
        f.write(str)    
    

Do I have to considerate an else? os.name has other alternatives ('posix', 'nt', 'os2', 'ce', 'java', 'riscos'). Should I use platform module instead?

Update 1:

  1. The goal is to use '\r\n' in any OS.

  2. I'm receiving the str from

    str = etree.tostring(root, pretty_print=True, xml_declaration=True, encoding='UTF-8')

I'm not reading a file.
3. My fault, I should probably check the os.linesep instead?


Solution

  • Python file objects can handle this for you. By default, writing to a text-mode file translates \n line endings to the platform-local, but you can override this behaviour.

    See the newline option in the open() function documentation:

    newline controls how universal newlines mode works (it only applies to text mode). It can be None, '', '\n', '\r', and '\r\n'. It works as follows:

    • When reading input from the stream, if newline is None, universal newlines mode is enabled. Lines in the input can end in '\n', '\r', or '\r\n', and these are translated into '\n' before being returned to the caller. If it is '', universal newlines mode is enabled, but line endings are returned to the caller untranslated. If it has any of the other legal values, input lines are only terminated by the given string, and the line ending is returned to the caller untranslated.
    • When writing output to the stream, if newline is None, any '\n' characters written are translated to the system default line separator, os.linesep. If newline is '' or '\n', no translation takes place. If newline is any of the other legal values, any '\n' characters written are translated to the given string.

    (the above applies to Python 3, Python 2 has similar behaviour, with io.open() giving you the Python 3 I/O options if needed).

    Set the newline option if you need to force what line-endings are written:

    with open('file', 'w', newline='\r\n') as f:
    

    In Python 2, you'd have to open the file in binary mode:

    with open('file', 'wb') as f:
        # write `\r\n` line separators, no translation takes place
    

    or use io.open() and write Unicode text:

    import io
    
    with io.open('file', 'w', newline='\r\n', encoding='utf8') as f:
         f.write(str.decode('utf8'))
    

    (but pick appropriate encodings; it is always a good idea to explicitly specify the codec even in Python 3).

    You can always use the os.linesep constant if your program needs to know the appropriate line separator for the current platform.