# csv.writer() 寫入 csv 檔後，每行間會多一空白行

**URL:** <https://vip.studycamp.tw/t/csvwriter-%E5%AF%AB%E5%85%A5-csv-%E6%AA%94%E5%BE%8C%EF%BC%8C%E6%AF%8F%E8%A1%8C%E9%96%93%E6%9C%83%E5%A4%9A%E4%B8%80%E7%A9%BA%E7%99%BD%E8%A1%8C/1746>\
**Category:** 常見語法\
**Tags:** csv\
**Created:** [2021年六月26日 08:11 UTC](https://vip.studycamp.tw/t/csvwriter-%E5%AF%AB%E5%85%A5-csv-%E6%AA%94%E5%BE%8C%EF%BC%8C%E6%AF%8F%E8%A1%8C%E9%96%93%E6%9C%83%E5%A4%9A%E4%B8%80%E7%A9%BA%E7%99%BD%E8%A1%8C/1746 "2021-06-26T08:11:46Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![sky](https://vip.studycamp.tw/user_avatar/vip.studycamp.tw/sky/32/8098_2.png) [@sky](https://vip.studycamp.tw/u/sky)\
**Post date:** [2021年六月26日 08:11 UTC](https://vip.studycamp.tw/t/csvwriter-%E5%AF%AB%E5%85%A5-csv-%E6%AA%94%E5%BE%8C%EF%BC%8C%E6%AF%8F%E8%A1%8C%E9%96%93%E6%9C%83%E5%A4%9A%E4%B8%80%E7%A9%BA%E7%99%BD%E8%A1%8C/1746/1 "2021-06-26T08:11:46Z")

</div>

## 解決方式

先講解答，原因下面說明。

```auto
import csv

# 這行指令會在每行間會多一空白行
with open('eggs.csv', 'w') as csvfile:

# 這個作法沒問題
with open('eggs.csv', 'w', newline='') as csvfile:

```

* * *

## 文件 vs. 範例

寫程式時，想要使用某函式，但沒用過或忘記時，大部分人是用 google 找答案。

這時有兩個方向：一個是看原始文件、另一個是看範例（特別是 stackoverflow 的問答）。

如果原始文件的範例寫得不錯，那當然最好。如果不足，那只好看其他人碰到類似情形時，是如何解決的。

我自己的習慣是先看範例，先解決問題再說，這個習慣不太好。

為什麼講 csv.writer() 會先說這麼多呢？因為這個問題的產生，就是碰到問題先找範例。

stackoverflow 的問答雖然常常能解決問題，但 **提醒大家要留意問與答個別的時間，盡量找比較新的問答。**

「csv.writer() 寫入 csv 檔後，每行間會多一空白行」

這個問題的產生，我當初就是因為直接參考 stackoverflow 的解答，然後又看到舊的。

雖然看到空白行很奇怪，但之前不影響我的目的，就沒仔細找原因。

* * *

## 原因

在原始文件中（最後一行，網址請見參考資料）有說：

```auto
如果沒有指定 newline='' ，則嵌入引號中的換行符將無法正確解析，
並且在寫入時，使用 \r\n 換行的平台會有多餘的 \r 寫入。
由於 csv 模塊會執行自己的（通用）換行符處理，因此指定 newline='' 應該總是安全的。

```

我用一張圖來補充說明

 ![csv.writer() 換行問題](https://vip.studycamp.tw/uploads/default/original/2X/5/54be11b2b266e597180903a9e93c205a9d1aee40.jpeg)

圖中四區塊，依序為：

1. with open(‘eggs.csv’, ‘w’, newline=‘’) as csvfile:

2. 上面 1 的結果，顯示檔案中的所有符號（包含換行）

3. with open(‘eggs.csv’, ‘w’) as csvfile:

4. 上面 3 的結果，顯示檔案中的所有符號（包含換行）

**\n 就是 LF 換行符號**  
**\r 就是 CR 回車符號**

CR 通常稱為回車符，如果你用過打字機就會知道，如果你只回車，忘記換行，接下來打的字，會重覆在剛剛打好的字上方。

* * *

## 參考資料

csv — CSV File Reading and Writing — Python 3.9.5 documentation

> **[csv — CSV File Reading and Writing](https://docs.python.org/3/library/csv.html#csv.writer)**
>
> The csv module defines the following functions: | Source code: Lib/csv.py The so-called CSV (Comma Separated Values) format is the most common import and export format for spreadsheets and databases. CSV format was used for many years prior to att...

換行 - 維基百科 裡面有 CR LF 的說明

> **[換行](https://zh.wikipedia.org/zh-tw/%E6%8F%9B%E8%A1%8C)**
>
> 換行（英語：newline、line ending、end-of-line (EOL)、line Feed (LF)、line break），在計算機領域中是加在一行文字最後位置的特殊字元，在換行字元的下一個字元將會出現在下一行。實際上換行字元根據不同的硬體平台或作業系統平台會有不同的編碼方式。
> 換行字元可以看作是行的結束符，也可以看作行之間的分隔符，這兩種處理方式之間存在一些歧義。如果換行字元被當作分隔符，那麼檔案的最後一行就不需要再有換行字元。但是多數系統的做法是在最後一行的後面也加上一個換行字元，也就是把換行字元看作是行的結束符。這樣的程式在處理末行沒有換行字元的檔案時，可能會存在問題。相反地，有的程式把換行符看作分隔符，就會把最末尾的換行字元看作是新行的開始，也就是多出了一個空行。
> 早期電腦系統常使用電傳打字機作為控制台裝置，需要使用CR+LF字元序列將印表機定位在新行的開頭。列印頭無法及時從最右邊返回到下一行的開頭來列印下一個字元。在CR之後列印的字元通常會在頁面中間列印為污跡，這是因為列印頭仍在移回行首位置的途中。「解決方案是將換行符設定為兩個字元：CR將列印頭Enter...

回車 (控制字元) - 維基百科

> **[回車 (控制字元)](https://zh.wikipedia.org/zh-tw/%E5%9B%9E%E8%BD%A6%E7%AC%A6)**
>
> 回車（英語：carriage return），常縮寫為CR，是指將定位裝置重設到文字行首的控制字元或過程，用以把一裝置的位置重設到一行字的頭。
> 原本，回車這術語用於打字機的板手。若打字機的語言由左至右書寫的語言．回車用於將承載裝紙滾筒的機架（carriage）移到最右邊，以便令印字位置對準一行的開頭，同時順便轉動滾筒，換至下一行。第一個有動力的回車功能是是在1960年由Smith Corona加入電打字機中，此鍵一般會標示為carriage return或return。
> 在非英語系國家的鍵盤上，符號↵（U+21B5、&crarr;）常用來表示回車與饋行的組合作用。
> 在ASCII和Unicode中，CR定義為13（十六進制為0D），也可以視為Ctrl+M或^M。其在C語言以及眾多受C語言影響的程式語言中，以\\r表示。

【轉貼】\_r\_n和\_n的差異 @ seacatcry的部落格 \_\_ 痞客邦 \_\_

> **[【轉貼】\\r\\n和\\n的差異](https://seacatcry.pixnet.net/blog/posts/8013732061)**
>
> 1.
> \\r\\n或是\\n都是換行的意思，請記得，是\\r\\n，不是\\n\\r
> \\r\\n通常是微軟的文件會產生的，在其它的編輯器裡面，會在一行的節尾看到 ^M，那就是\\r\\n
> 在php中，字串中的\\r\\n或\\n，要用雙引號才有效。

windows - CSV file written with Python has blank lines between each row - Stack Overflow

> <https://stackoverflow.com/questions/3348460/csv-file-written-with-python-has-blank-lines-between-each-row>
