Python換行符問題: 還是 ?

執行以下Python代碼:

fn = "test.txt"

file(fn, "w+").write("test
test2")

content = file(fn, "r").read()

print content.replace("
", "\r").replace("
", "\n")

列印的結果不依賴平台,都是:

test
test2

但是test.txt的內容卻依賴平台而變化(用notepad++、vi等程序查看):

windows下是:test
test2

linux下卻是:test
test2

我想問的問題是,如何保證Python寫入文件的"
"字元不隨平台變化,即保證一定是"
"?


章碩,js python
夏一一、喬3少 贊同
這不是python的問題,windows的換行是
,unix的是
,mac的是

這是一個很經典的問題。因為不同系統下默認的換行符不同。字元處理時候,這樣的「不同」會帶來很大的問題,例如line[-2]和line.strip()會因為平台不同返回不同的值。

解決方法:

Python 2

PEP 278 -- Universal Newline Support,感謝畢勤的補充):

1)如果不是txt文件,建議用wb和rb來讀寫。通過二進位讀寫,不會有換行問題。

2)如果需要明文內容,請用rU來讀取(強烈推薦),即U通用換行模式(Universal new line mode)。該模式會把所有的換行符(

)替換為
只支持讀入,但是也足夠了。這是Python 提供給我們的最好的選擇,沒有之一。

對比r和rU的結果:

content = file(fn, "r").read()
# test
test2
# 這裡的換行會因不同系統而不同
content = file(fn, "rU").read()
# test
test2
# 所有的換行都被統一,不分系統

Python 3

(Open函數: 2. Built-in Functions,感謝林誠的補充)

請注意:Python 3不推薦用rU模式!

open(file, mode="r", buffering=-1, encoding=None, errors=None, newline=None, closefd=True)

在Python 3,可以通過open函數的newline參數來控制Universal new line mode:讀取時候,不指定newline,則默認開啟Universal new line mode,所有
,
, or
被默認轉換為
;寫入時,不指定newline,則換行符為各系統默認的換行符(
,
, or
, ),指定為newline="
",則都替換為
(相當於Universal new line mode);不論讀或者寫時,newline=""都表示不轉換。

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

  • On input, if newline is None, universal newlines mode is enabled. Lines in the input can end in "
    ", "
    ", or "
    ", and these are translated into "
    " before being returned to the caller. If it is "", universal newline 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.
  • On output, if newline is None, any "
    " characters written are translated to the system default line separator,
    os.linesep. If newline is "", no translation takes place. If newline is any of the other legal values, any "
    " characters written are translated to the given string.

參考文獻:

PEP 278 -- Universal Newline Support

Python 3 open: 2. Built-in Functions


file(fn, "w+").write("test
test2")

改成

file(fn, "wb+").write("test
test2")

就行了。Windows 平台上 Python 區分 Binary 和 ASCII 模式。ASCII 模式下換行符會在讀寫時自動換為
(詳見 [1])。*nix 平台下沒有這個區別。

[1]: http://docs.python.org/tutorial/inputoutput.html#reading-and-writing-files


現在這個答案已經錯了0.0,正確如下(在不可預見的未來,這個答案也很可能錯了,期待有人@我)。

在遠古時代:windows的換行是
,unix的是
,mac的是
完全正確!

Mac OS 9 以及之前的系統的換行符是 CR(
),從 Mac OS X (後來改名為「OS X」)開始的換行符是 LF(
)。

參考Did Mac OS Lion switch to using line feeds (LF "
") for line breaks instead of carriage returns (CR "
")?


python可以根據系統自動選擇換行符,只要使用 os.linesep 就可以判斷出來


這不是python的問題,windows的換行是
,unix的是
,mac的是


我知道的一點是:CLRF結尾的文件可以用【dos2unix】命令轉換為RF結尾的文件。


回答除了第一個都略微偏題了. 個人習慣來說,當編輯文件時,盡量使用二進位格式,這樣會避免跨平台時出錯. 根本不需要知道每個平台是
,還是
. 只要養成 rb,wb等習慣就行了. Rio 就是一個很好的編程習慣.


不特別指定的話,python會自適應各個平台的差異,比如

的不同。

想達到樓主的目地,可以用二進位模式打開和操作文件即可。


推薦閱讀:

如何用Yacc實現一個Python的編譯器?
為什麼大多數編程語言被設計成函數只有一個返回值,而不是多個?
用 Python 做策略回測,耗時很長,有什麼加速辦法?

TAG:MicrosoftWindows | Python | Unix |