Đường phân chia tệp python

Trong Python, bạn mở một tệp bằng cách sử dụng hàm open() tích hợp và chuyển cho nó đường dẫn đến tệp bạn muốn mở. Theo mặc định, các tệp được mở ở dạng chỉ đọc

Đây là một ví dụ rất cơ bản về việc mở và đọc một tệp là thư mục hiện tại

f = open('myfile.txt')
contents = f.read()
print(contents)

f.read() chỉ đọc toàn bộ tệp dưới dạng một chuỗi thành một biến. Vì vậy, điều này sẽ chỉ in toàn bộ nội dung của tệp

Ngoài ra, bạn có thể muốn đọc tệp thành một danh sách, mỗi lần một dòng. Bạn có thể làm điều đó với phương pháp

f = open('myfile.txt')
file_as_list = f.readlines()
for line in file_as_list:
  print(line)
0

f = open('myfile.txt')
file_as_list = f.readlines()
for line in file_as_list:
  print(line)

Kết quả có thể làm bạn ngạc nhiên mặc dù. Khi được in, mỗi dòng sẽ được theo sau bởi hai ký tự xuống dòng. Đó là bởi vì

f = open('myfile.txt')
file_as_list = f.readlines()
for line in file_as_list:
  print(line)
0 không tách ký tự xuống dòng khi tách nội dung thành danh sách. Mỗi mục danh sách sẽ kết thúc bằng ký tự xuống dòng. Điều đó chiếm một trong những ký tự dòng mới. Theo mặc định, ký tự xuống dòng khác xuất hiện ở cuối mỗi cuộc gọi đến
f = open('myfile.txt')
file_as_list = f.readlines()
for line in file_as_list:
  print(line)
2

Điều này có liên quan đến lỗi 18291. Có lẽ một số người sẽ ngạc nhiên rằng str. splitlines() phân chia thành nhiều thứ khác ngoài các ký tự xuống dòng (\n) và ký tự xuống dòng (\r). Điều đó không giống như đối tượng str trong Python 2. Xem tài liệu cho. Bởi vì mô-đun codec sử dụng str. splitlines nội bộ, bạn sẽ có hành vi chia dòng khác nhau khi bạn sử dụng codec. getreader() so với sử dụng open() với tệp chế độ văn bản

Tôi không thấy ý nghĩa của việc các đường phân tách () coi tất cả các ký tự điều khiển bổ sung này là các đường phân tách. Nếu tôi xem xét việc sử dụng splitlines() trong stdlib, có vẻ như mọi người thường muốn hành vi phân tách giống như những gì tệp

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
5 thực hiện. Tôi sẽ không ngạc nhiên nếu có lỗi thực sự, một số lỗi liên quan đến bảo mật, do hành vi này

Sau khi thực hiện một số thao tác đào, có vẻ như hành vi này quay trở lại khi loại

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
6 như được giới thiệu trong Python 2. Tôi nghi ngờ khi mã được chuyển đổi từ 2 sang 3, splitlines() đã thay đổi từ hoạt động trên byte sang hoạt động trên chuỗi unicode. Và, tôi cá là mọi người đã không nhận ra sự khác biệt trong hành vi này

IMHO, lý tưởng nhất là trường hợp

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
7

Tôi đang đăng ở đây vì tôi không biết liệu đây có phải là điều chúng ta có thể thay đổi hay không, vì đó có thể là hành vi mà mọi người đang dựa vào

Có một số lỗi trong trình theo dõi vấn đề liên quan đến điều này, một số mở, một số đóng. Tôi đã tìm thấy lỗi 22232 có vẻ phù hợp nhất (str. các đường phân tách chia tách trên các ký tự không phải\r\n). Bây giờ tôi không chắc mình có nên đưa cuộc thảo luận vào đây không, có lẽ tôi nên giữ nó bên trong trình theo dõi vấn đề

Marc-Andre Lemburg đã nhận xét về vấn đề này và là -1 khi thay đổi str. hành vi splitlines và cũng không nghĩ rằng

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
8 nên được thay đổi. Tôi có thể thấy lập luận của anh ấy từ quan điểm thuần khiết của Unicode. Tuy nhiên, đối với tôi, có vẻ như hành vi này tạo ra nhiều lỗi hơn là hữu ích. Đặt tên unicode. phương pháp splitlines giống như str. splitlines là một sai lầm, IMHO

Nếu tôi xem xét việc sử dụng

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
9 trong thư viện chuẩn Python và trong 50 gói PyPi hàng đầu, gần như mọi trường hợp dường như mong đợi được phân tách trên '\r' và '\n' hoặc chỉ trên '\n'. Trong hầu hết các trường hợp, mã này khớp với mã Python 2 và thường thì giá trị được chia là
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
0. Tôi chưa tìm thấy bất kỳ trường hợp nào rõ ràng là mong muốn tách kiểu Unicode. Vì vậy, đó là lý do tại sao tôi cảm thấy Marc-Andre đang tranh luận về sự thuần khiết hơn là tính thực tế

Thêm một phương pháp mới như

argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
1 có thể là giải pháp tốt nhất. Nếu chúng tôi làm như vậy, tôi nghĩ nó chỉ nên tách trên \and, vì vậy nó khớp với
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
2 trên các đối tượng tệp. Chúng ta nên cung cấp cho nó một từ khóa
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
3 để việc sửa các cuộc gọi của
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
4 trở nên dễ dàng. Sau đó, chúng tôi phải kiểm tra tất cả các cách sử dụng của
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
4 và hầu hết chúng cần được thay đổi thành
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
1

Tôi muốn đối tượng người đọc

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
8 nhận tham số từ khóa
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
8 và để nó hoạt động giống như phiên bản
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
9. Sau đó, các mô-đun như
linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname
0 phải có cách để kiểm tra xem
linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname
1 đã được sử dụng chưa và cảnh báo nếu chưa. Đối với tôi, có vẻ như có nhiều lỗi liên quan đến hành vi phân tách Unicode này. Bắt đầu đặt các ký tự \v trong tiêu đề giao thức, trường tệp CSV, v.v. và bạn sẽ thấy nhiều hành vi không mong muốn

Đây là một phân tích nhanh về việc sử dụng

linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname
2 bên trong stdiib. Không rõ mục đích là gì (hoặc thậm chí nếu đôi khi dữ liệu là
argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
0 hoặc
linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname
4). Vì vậy, hãy coi phân tích của tôi như muối bỏ bể khi tôi đã thực hiện nó một cách nhanh chóng

codecs.py
509:                    lines = newchars.splitlines(keepends=True)
551:                line = line.splitlines(keepends=False)[0]
568:            lines = line.splitlines(keepends=True)
584:                        line = line.splitlines(keepends=False)[0]
587:                line0withoutend = lines[0].splitlines(keepends=False)[0]
600:                    line = line.splitlines(keepends=False)[0]
619:        return data.splitlines(keepends)
822:        return data.splitlines(keepends=True)

Marc-Andre gợi ý rằng codec nên chia dòng theo Unicode
ISNEWLINE quy tắc và không được khớp với tệp. readlines() cho tệp văn bản. tôi nghĩ
nếu không thì hãy để lại trường hợp này. Ở mức tối thiểu, tôi nghĩ getreader() nên
nhận một tùy chọn

argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():
8 để làm cho nó khớp với những gì open() làm

nntplib.py
896:            f = f.splitlines()

Trong trường hợp này,

linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname
6 là byte nên điều này có thể ổn. Không chắc chắn tách trên băng \r
được rồi

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)

Chỉ tách trên '\n'

argparse.py
655:        return ''.join(indent + line for line in text.splitlines(keepends=True))
666:        return text.splitlines()
2047:                        for arg_line in args_file.read().splitlines():

Chỉ tách trên '\n'

linecache.py
113:                    [line+'\n' for line in data.splitlines()], fullname

Chỉ tách trên '\n'

pprint.py
250:        lines = object.splitlines(True)

Chỉ tách trên '\n'

difflib.py
785:    .. '''.splitlines(keepends=True)
794:    .. '''.splitlines(keepends=True)
880:        >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
881:        ..                                'ore\ntree\nemu\n'.splitlines(True))),
1247:    >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True),
1248:    ..       'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')),
1366:    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
1367:    ..              'ore\ntree\nemu\n'.splitlines(keepends=True))
2070:    >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
2071:    ..              'ore\ntree\nemu\n'.splitlines(keepends=True))

Tách trên '\n' hoặc '\r'?

pydoc.py
288:            result = module.__doc__.splitlines()[0] if module.__doc__ else None
2155:                    desc = module.__doc__.splitlines()[0] if module.__doc__ else ''

Chỉ tách trên '\n'

smtpd.py
709:        lines = data.splitlines()

Tách trên '\r' hoặc '\n'?

site.py
180:                    for line in record.splitlines():

Chỉ tách trên '\n'

nntplib.py
896:            f = f.splitlines()
0

Tách theo Unicode ISNEWLINE?
cũng tốt

nntplib.py
896:            f = f.splitlines()
1

Được rồi, đây là byte

nntplib.py
896:            f = f.splitlines()
2

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
3

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
4

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
5

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
6

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
7

Chỉ tách trên '\n'?

nntplib.py
896:            f = f.splitlines()
8

Chỉ tách trên '\n'

nntplib.py
896:            f = f.splitlines()
9

Chỉ tách trên '\n'

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
0

Tách trên '\n' hoặc '\r'?

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
1

Tách trên '\n' hoặc '\r'?

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
2

Tách trên '\n'

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
3

Tách trên '\n'

doctest.py
1413:            return example.source.splitlines(keepends=True)
1676:            want_lines = want.splitlines(keepends=True)
1677:            got_lines = got.splitlines(keepends=True)
4

Tách trên '\n'

Tôi không thấy cách hành vi hiện tại là một mặc định tốt. Tôi có thể hiểu nếu chúng tôi không thể thay đổi nó do tính tương thích ngược. Tôi có thể lập luận rằng chúng ta sẽ làm nhiều điều tốt hơn là làm hại bằng cách thay đổi nó

Chúng tôi đã có cuộc thảo luận về trình theo dõi lỗi

Tóm lại tình hình là thế này

Khi Unicode được thêm vào, tôi đã tập trung vào việc đưa ra các quyết định thiết kế phù hợp từ góc độ Unicode. Unicode xác định nhiều ngắt dòng hơn ASCII, vì vậy chúng tôi phải bao gồm tất cả chúng để phù hợp với tiêu chuẩn, giống như Unicode xác định nhiều ký tự hơn có thể được hiểu là chữ số hoặc thậm chí là số nguyên và các phương thức tương ứng, chẳng hạn như. isdigit() đã được mở rộng. Điều này là cần thiết, vì đối tượng Unicode trong Python được cho là đại diện cho Unicode theo tiêu chuẩn

Bây giờ, khi Python 3 chuyển sang sử dụng Unicode thay vì byte cho “str”, chúng tôi đã nhận được ngữ nghĩa Unicode, nhưng không thực sự thông qua stdlib (hoặc mã khác) được viết với ngữ nghĩa ASCII trong một số phần. Trong một số trường hợp, điều này hữu ích, trong những trường hợp khác thì không, vì giờ đây Python sẽ nhận ra nhiều "ký tự" dưới dạng ngắt dòng hoặc chữ số hơn so với kế hoạch ban đầu của quy trình tương ứng. tác giả mã

Sau ngần ấy thời gian, tôi không nghĩ rằng chúng ta có thể thay đổi ngữ nghĩa một cách triệt để nữa và đơn giản là phải chấp nhận rằng chúng ta đã không xem xét kỹ các hàm ý khi chuyển từ str=bytes sang str=unicode

Nhìn chung, tôi không nghĩ có nhiều trường hợp ngữ nghĩa Unicode gây ra vấn đề trong cuộc sống thực. Một vài ký tự cuối dòng bổ sung rất hiếm khi được sử dụng trong thực tế và rất có thể sẽ chỉ ra các vấn đề với dữ liệu, thay vì các vấn đề với mã, trong những trường hợp bạn không muốn các điểm mã mới được hiểu là ngắt dòng

Nếu bạn thực sự đang làm việc với văn bản Unicode chứ không phải với văn bản ASCII mà bạn tình cờ nhận được dưới dạng Uncode str, thì bạn thực sự muốn các ngắt dòng này, vì đó là những gì Unicode định nghĩa và những gì tác giả của văn bản sẽ sử dụng làm cơ sở để viết văn bản. chữ. Về mặt này, hành động của. splitlines() là chính xác. Nó chỉ không đúng đối với các tiêu chuẩn chỉ bắt buộc các ký tự ngắt dòng ASCII

Tôi nghĩ đối với mã chắc chắn chỉ có thể bị hỏng trên các dòng mới ASCII, chúng ta nên tạo một phương thức mới (e. g. . asciilines()) hoặc thêm một tham số vào. splitlines() hạn chế tập hợp các ký tự được chia thành các ký tự ASCII mà chúng tôi đã có trong Python 2