Tệp CSV được viết bằng Python có các dòng trống giữa mỗi hàng


446
import csv

with open('thefile.csv', 'rb') as f:
  data = list(csv.reader(f))
  import collections
  counter = collections.defaultdict(int)

  for row in data:
        counter[row[10]] += 1


with open('/pythonwork/thefile_subset11.csv', 'w') as outfile:
    writer = csv.writer(outfile)
    for row in data:
        if counter[row[10]] >= 504:
           writer.writerow(row)

Mã này đọc thefile.csv, thực hiện thay đổi và ghi kết quả vào thefile_subset1.

Tuy nhiên, khi tôi mở csv kết quả trong Microsoft Excel, có một dòng trống thêm sau mỗi bản ghi!

Có cách nào để làm cho nó không đặt thêm một dòng trống?


4
Vui lòng xác nhận rằng điều này xảy ra khi bạn chạy mã đó trên Windows
John Machin

Bản sao có thể có của trình soạn thảo CSV 2
John Y

Xem câu trả lời trên chủ đề này: stackoverflow.com/questions/3348460/ từ
Febin Mathew

Câu trả lời:


886

Trong Python 2, mở outfilebằng chế độ 'wb'thay vì 'w'. Việc csv.writerghi \r\nvào tập tin trực tiếp. Nếu bạn không mở tệp ở chế độ nhị phân , nó sẽ ghi \r\r\nvì trên chế độ văn bản Windows sẽ dịch từng tệp \nthành \r\n.

Trong Python 3, cú pháp bắt buộc đã thay đổi (xem các liên kết tài liệu bên dưới), vì vậy hãy mở outfilebằng tham số bổ sung newline=''(chuỗi trống).

Ví dụ:

# Python 2
with open('/pythonwork/thefile_subset11.csv', 'wb') as outfile:
    writer = csv.writer(outfile)

# Python 3
with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:
    writer = csv.writer(outfile)

Liên kết tài liệu


1
Dù sao, câu trả lời của @Mark Tolonen đã giải quyết được nhiều câu hỏi liên quan đến (các) dòng bổ sung được thêm khi lưu tệp văn bản tiêu chuẩn (không sử dụng csv).
dlewin

1
Để tương thích giữa 2.6 / 2.7 và 3, bạn có thể sử dụng io.openvới newlinesđối số. Nếu bạn vẫn đang viết bằng 2.x, dù sao thì đó dường như là một lựa chọn tốt hơn vì nó tương thích về phía trước.
jpmc26

@ jpmc26 Thông thường đó là lời khuyên tốt, nhưng mô-đun csv không hoạt động đúng io.open. Có một unicodecsvmô-đun bên thứ 3 cho Python 2.7 hoạt động tốt hơn.
Mark Tolonen

Bất cứ ý tưởng tại sao newline=''thủ thuật không hoạt động trong python3 với StringIO hoặc Tạm thời?
fmoo

@fmoo định nghĩa "không hoạt động". Cả hai đều làm việc theo cách tôi mong đợi. StringIOđệm các điểm mã giống nhau sẽ được mã hóa vào một tệp và TemporaryFilehỗ trợ newlinetham số, vì vậy nó có thể được mở như với open. Đặt câu hỏi với một chương trình mẫu không hoạt động.
Đánh dấu Tolonen

65

Mở tệp ở chế độ nhị phân "wb" sẽ không hoạt động trong Python 3+. Hay đúng hơn, bạn phải chuyển đổi dữ liệu của mình thành nhị phân trước khi viết nó. Đó chỉ là một rắc rối.

Thay vào đó, bạn nên giữ nó ở chế độ văn bản, nhưng ghi đè lên dòng mới là trống. Thích như vậy:

with open('/pythonwork/thefile_subset11.csv', 'w', newline='') as outfile:

13

Câu trả lời đơn giản là các tệp csv phải luôn được mở ở chế độ nhị phân cho dù là đầu vào hay đầu ra, vì nếu không thì trên Windows có vấn đề với dòng kết thúc. Cụ thể ở đầu ra, mô-đun csv sẽ ghi \r\n(bộ kết thúc hàng CSV tiêu chuẩn) và sau đó (ở chế độ văn bản), bộ thực thi sẽ thay thế \nbằng \r\n(bộ kết thúc dòng tiêu chuẩn Windows) cho kết quả \r\r\n.

Đấu tranh với lineterminatorKHÔNG phải là giải pháp.


"Tiêu chuẩn" CSV này mà bạn nói là gì?
Dan Breslau

3
@Dan: Tôi đã sử dụng "tiêu chuẩn" như một tính từ, không phải danh từ, có nghĩa là "thông thường" hoặc "thông thường". Nếu bạn muốn gần đúng với một tiêu chuẩn (danh từ), hãy đọc tools.ietf.org/html/rfc4180
John Machin

1
Điểm là (như bạn ngụ ý) rằng không có tiêu chuẩn. RFE đó là thông tin. Mặc dù \ r \ n có thể là "tiêu chuẩn" trên Windows, tôi chắc chắn các ứng dụng Unix thường không thấy như vậy.
Dan Breslau

2
@Dan: Đúng vậy - không có tiêu chuẩn. Các tập lệnh nên chỉ định lineterminator [nên được đặt tên là ROWterminator] mà chúng muốn (nếu không phải là mặc định) và vẫn sử dụng chế độ nhị phân trong trường hợp tập lệnh được chạy trên Windows nếu không "lineterminator" có thể bị nhồi.
John Machin

8

Lưu ý: Có vẻ như đây không phải là giải pháp ưa thích vì cách thêm dòng bổ sung trên hệ thống Windows. Như đã nêu trong tài liệu python :

Nếu csvfile là một đối tượng tệp, nó phải được mở bằng cờ 'b' trên các nền tảng tạo ra sự khác biệt.

Windows là một trong những nền tảng như vậy, nơi tạo ra sự khác biệt. Trong khi thay đổi bộ kết thúc dòng như tôi mô tả dưới đây có thể đã khắc phục sự cố, vấn đề có thể tránh được hoàn toàn bằng cách mở tệp ở chế độ nhị phân. Người ta có thể nói giải pháp này là "thanh lịch" hơn. "Đánh nhau" với bộ kết thúc dòng có thể sẽ dẫn đến mã không thể truy cập giữa các hệ thống trong trường hợp này, trong đó việc mở tệp ở chế độ nhị phân trên hệ thống unix không có kết quả. I E. nó dẫn đến mã tương thích hệ thống chéo.

Từ tài liệu Python :

Trên Windows, 'b' được thêm vào chế độ sẽ mở tệp ở chế độ nhị phân, do đó, cũng có các chế độ như 'rb', 'wb' và 'r + b'. Python trên Windows phân biệt giữa các tệp văn bản và tệp nhị phân; các ký tự cuối dòng trong tệp văn bản sẽ tự động được thay đổi một chút khi dữ liệu được đọc hoặc ghi. Điều chỉnh hậu trường này đối với dữ liệu tệp là tốt đối với các tệp văn bản ASCII, nhưng nó sẽ làm hỏng dữ liệu nhị phân như trong các tệp JPEG hoặc EXE. Hãy thật cẩn thận khi sử dụng chế độ nhị phân khi đọc và ghi các tệp như vậy. Trên Unix, việc nối thêm 'b' vào chế độ sẽ không ảnh hưởng gì, vì vậy bạn có thể sử dụng nó độc lập với nền tảng cho tất cả các tệp nhị phân.

Bản gốc :

Là một phần của các tham số tùy chọn cho csv.writer nếu bạn nhận được thêm các dòng trống, bạn có thể phải thay đổi lineterminator (thông tin ở đây ). Ví dụ dưới đây thích nghi từ các tài liệu csv trang python . Thay đổi nó từ '\ n' thành bất cứ điều gì cần. Vì đây chỉ là một cú đâm trong bóng tối về vấn đề này có thể có hoặc không hoạt động, nhưng đó là phỏng đoán tốt nhất của tôi.

>>> import csv
>>> spamWriter = csv.writer(open('eggs.csv', 'w'), lineterminator='\n')
>>> spamWriter.writerow(['Spam'] * 5 + ['Baked Beans'])
>>> spamWriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

Tôi chuẩn bị đăng bài về điều này - lineterminator = '\ n' đã làm việc cho tôi trong một thử nghiệm đơn giản.
Dan Breslau

tôi có thể làm điều này> ?? với open ('/ pythonwork / thefile_subset11.csv', 'w'), lineterminator = '\ n' là outfile:
l --''''''--------- '' '' ' '' '' ''

1
@I__: Bạn thực sự nên bắt đầu lướt qua các tài liệu Python. Derek đã cung cấp cho bạn liên kết: docs.python.org/l Library / csv.html
Dan Breslau

5

Tôi đang viết câu trả lời này viết cho python 3, vì ban đầu tôi cũng gặp vấn đề tương tự.

Tôi đã phải lấy dữ liệu từ arduino bằng cách sử dụng PySerialvà ghi chúng vào tệp .csv. Mỗi lần đọc trong trường hợp của tôi kết thúc bằng '\r\n', vì vậy dòng mới luôn tách biệt từng dòng.

Trong trường hợp của tôi, newline=''tùy chọn không hoạt động. Bởi vì nó cho thấy một số lỗi như:

with open('op.csv', 'a',newline=' ') as csv_file:

ValueError: illegal newline value: ''

Vì vậy, dường như họ không chấp nhận bỏ sót dòng mới ở đây.

Chỉ thấy một trong những câu trả lời ở đây, tôi đã đề cập đến dòng kết thúc trong đối tượng nhà văn, như,

writer = csv.writer(csv_file, delimiter=' ',lineterminator='\r')

và điều đó đã làm việc cho tôi để bỏ qua các dòng mới.


2
Điều này là không chính xác. with open('my_file.csv', 'a',newline='') as csvfile: hoạt động hoàn toàn tốt Vấn đề với câu trả lời của bạn là ở đây bạn đang viết ' 'thay vì''
Nasrin

2
with open(destPath+'\\'+csvXML, 'a+') as csvFile:
    writer = csv.writer(csvFile, delimiter=';', lineterminator='\r')
    writer.writerows(xmlList)

Giấy phép "lineterminator = '\ r'" để chuyển sang hàng tiếp theo, không có hàng trống giữa hai.


1

Mượn từ câu trả lời này , có vẻ như giải pháp sạch nhất là sử dụng io.TextIOWrapper. Tôi đã tự mình giải quyết vấn đề này như sau:

from io import TextIOWrapper

...

with open(filename, 'wb') as csvfile, TextIOWrapper(csvfile, encoding='utf-8', newline='') as wrapper:
    csvwriter = csv.writer(wrapper)
    for data_row in data:
        csvwriter.writerow(data_row)

Câu trả lời ở trên không tương thích với Python 2. Để có khả năng tương thích, tôi cho rằng người ta chỉ cần bọc tất cả logic viết trong một ifkhối:

if sys.version_info < (3,):
    # Python 2 way of handling CSVs
else:
    # The above logic

0

Sử dụng phương pháp được xác định bên dưới để ghi dữ liệu vào tệp CSV.

open('outputFile.csv', 'a',newline='')

Chỉ cần thêm một newline=''tham số bổ sung bên trong openphương thức:

def writePhoneSpecsToCSV():
    rowData=["field1", "field2"]
    with open('outputFile.csv', 'a',newline='') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(rowData)

Điều này sẽ viết các hàng CSV mà không tạo các hàng bổ sung!


-1

Khi sử dụng Python 3, các dòng trống có thể tránh được bằng cách sử dụng mô-đun codec . Như đã nêu trong tài liệu, các tệp được mở ở chế độ nhị phân nên không cần thay đổi kwarg dòng mới. Gần đây tôi đã gặp phải vấn đề tương tự và điều đó có hiệu quả với tôi:

with codecs.open( csv_file,  mode='w', encoding='utf-8') as out_csv:
     csv_out_file = csv.DictWriter(out_csv)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.