• Python CSV Reader/Writer 例子--转载


    CSV(comma-separated values) 是跨多种形式导入导出数据的标准格式,比如 MySQL、Excel。

    它以纯文本存储数和文本。文件的每一行就代表一条数据,每条记录包含了由逗号分隔的一个或多个属性值。这个标准格式的名字来源就是每条记录是用逗号将其属性分隔的。

    即使有这个非常明显的命名标准,而实际上却没有一个官方的标准 CSV 格式,有可能是以一些比较类似的分隔符来分隔数据,虽然它们的扩展是 .csv 但是实际上却用了各种符号,空格、tab,这些也是比较流行的符号。有时由于缺少严格的定义使得数据移植变得很困难。

    RFC 4180 提供了一些标准:

    • 内容为纯文本
    • 包含记录
    • 每条记录是用单个分隔字符将各属性分隔
    • 每条记录的属性序列是相同的

    除非提供的 CSV 文件有额外的说明信息(比如使用 RFC 提供的标准),否则处理这种数据格式将是相当烦人的。

    1.基础

    Python 天生支持读取 CSV 格式数据并且是可配置的(这个我们看到是必不可少的)。在 Python 里边有个模块 csv ,它包含了 CSV 读取/生成所需的所有支持,并且它遵守 RFC 标准(除非你覆盖了相应的配置),因此默认情况下它是能够读取和生成合法的 CSV 文件。

    那么,我们看看它是如何工作的:

    [java] view plain copy
     
    1. import csv  
    2. with open('my.csv', 'r+', newline='') as csv_file:  
    3.     reader = csv.reader(csv_file)  
    4.     for row in reader:  
    5.         print(str(row))  

    代码中我们导入了 csv 模块并且打开了 "my.csv" 文件,将文件作为参数传给 csv.reader,调用这个方法后我们将 reader 里边的每行数据输出。

    假设 'my.csv' 里边的内容为:

     

    [python] view plain copy
     
    1. my first column,my second column,my third column  
    2. my first column 2,my second column 2,my third column 2  

    那么我们运行这个代码后,相应的输出:

     

    [python] view plain copy
     
    1. ['my first column', 'my second column', 'my third column']  
    2. ['my first column 2', 'my second column 2', 'my third column 2']  

    生成和读取一样的简单:

    [java] view plain copy
     
    1. import csv  
    2. rows = [['1', '2', '3'], ['4', '5', '6']]  
    3. with open('my.csv', 'w+', newline='') as csv_file:  
    4.     writer = csv.writer(csv_file)  
    5.     for row in rows:  
    6.         writer.writerow(row)  
    7.   
    8. with open('my.csv', 'r+', newline='') as csv_file:  
    9.     reader = csv.reader(csv_file)  
    10.     for row in reader:  
    11.         print(str(row))  



    在 csv 文件的数据会是:

    [python] view plain copy
     
    1. 1,2,3  
    2. 4,5,6  

    输出的内容:

     

    [python] view plain copy
     
    1. ['1', '2', '3']  
    2. ['4', '5', '6']  

    到这里我们都非常清楚代码逻辑。我们将文件作为参数给 writer,以写模式打开,然后用它来写每一行数据。下边是更灵活的方式:

    [java] view plain copy
     
    1. import csv  
    2.   
    3. def read(file_location):  
    4.     with open(file_location, 'r+', newline='') as csv_file:  
    5.         reader = csv.reader(csv_file)  
    6.         return [row for row in reader]  
    7.   
    8. def write(file_location, rows):  
    9.     with open(file_location, 'w+', newline='') as csv_file:  
    10.         writer = csv.writer(csv_file)  
    11.         for row in rows:  
    12.             writer.writerow(row)  
    13.   
    14. def raw_test():  
    15.     columns = int(input("How many columns do you want to write? "))  
    16.     input_rows = []  
    17.     keep_going = True  
    18.     while keep_going:  
    19.         input_rows.append([input("column {}: ".format(i + 1)) for i in range(0, columns)])  
    20.         ui_keep_going = input("continue? (y/N): ")  
    21.         if ui_keep_going != "y":  
    22.             keep_going = False  
    23.   
    24.     print(str(input_rows))  
    25.   
    26.     write('raw.csv', input_rows)  
    27.     written_value = read('raw.csv')  
    28.     print(str(written_value))  
    29.   
    30. raw_test()  



    我们询问用户每行需要的列数然后是否继续输入下一行,随后我们输出读入的一般数据并且将这些内容生成到一个叫 raw.csv,然后继续这样一个过程。当我们运行这个程序,相关的内容如下:

     

    [python] view plain copy
     
    1. How many columns do you want to write? 3  
    2. column 1: row 1, column 1  
    3. column 2: row 1, column 2  
    4. column 3: row 1, column 3  
    5. continue? (y/N): y  
    6. column 1: row 2, column 1  
    7. column 2: row 2, column 2  
    8. column 3: row 3, column 3  
    9. continue? (y/N):   
    10. [['row 1, column 1', 'row 1, column 2', 'row 1, column 3'], ['row 2, column 1', 'row 2, column 2', 'row 3, column 3']]  
    11. [['row 1, column 1', 'row 1, column 2', 'row 1, column 3'], ['row 2, column 1', 'row 2, column 2', 'row 3, column 3']]  
    12.   
    13. Process finished with exit code 0  

    当然我们的 raw.csv 内容是:

     

    [python] view plain copy
     
    1. "row 1, column 1","row 1, column 2","row 1, column 3"  
    2. "row 2, column 1","row 2, column 2","row 3, column 3"  

    CSV 格式的另一个规则就是引号。在上边的例子中,每一个输入都包含一个逗号,而逗号是我们的分隔符,所以这个逗号被放到了引号(标准的默认值)中间表示在此间的并非分隔符而只是每列中的符号而已。

    虽让我推荐保留标准的配置信息,不过也存在一些情况需要更改默认配置,毕竟你没法控制的数据提供方给出的 csv 文件。因此,我不得不教你如何调整配置(beware, 责任越大权力越大)。

    你能够通过设置 delimiter 和 quotechar 来配置分隔符和引用符:

     

    [python] view plain copy
     
    1. import csv  
    2.   
    3.   
    4. def read(file_location):  
    5.     with open(file_location, 'r+', newline='') as csv_file:  
    6.         reader = csv.reader(csv_file, delimiter=' ', quotechar='|')  
    7.         return [row for row in reader]  
    8.   
    9.   
    10. def write(file_location, rows):  
    11.     with open(file_location, 'w+', newline='') as csv_file:  
    12.         writer = csv.writer(csv_file, delimiter=' ', quotechar='|')  
    13.         for row in rows:  
    14.             writer.writerow(row)  
    15.   
    16.   
    17. def raw_test():  
    18.     columns = int(input("How many columns do you want to write? "))  
    19.     input_rows = []  
    20.     keep_going = True  
    21.     while keep_going:  
    22.         input_rows.append([input("column {}: ".format(i + 1)) for i in range(0, columns)])  
    23.         ui_keep_going = input("continue? (y/N): ")  
    24.         if ui_keep_going != "y":  
    25.             keep_going = False  
    26.   
    27.     print(str(input_rows))  
    28.   
    29.     write('raw.csv', input_rows)  
    30.     written_value = read('raw.csv')  
    31.     print(str(written_value))  
    32.   
    33. raw_test()  

    现在我们的输出值为:

     

    [python] view plain copy
     
    1. How many columns do you want to write? 3  
    2. column 1: row 1 column 1  
    3. column 2: row 1 column 2  
    4. column 3: row 1 column 3  
    5. continue? (y/N): y  
    6. column 1: row 2 column 1  
    7. column 2: row 2 column 2  
    8. column 3: row 2 column 3  
    9. continue? (y/N):   
    10. [['row 1 column 1', 'row 1 column 2', 'row 1 column 3'], ['row 2 column 1', 'row 2 column 2', 'row 2 column 3']]  
    11. [['row 1 column 1', 'row 1 column 2', 'row 1 column 3'], ['row 2 column 1', 'row 2 column 2', 'row 2 column 3']]  

    我们的 raw.csv 文件中结果是:

     

    [python] view plain copy
     
    1. |row 1 column 1| |row 1 column 2| |row 1 column 3|  
    2. |row 2 column 1| |row 2 column 2| |row 2 column 3|  

    我们可以看到,新分隔符已经变成了空格,而我们的引用符变成了管道,这主要是空格在每个文本数据中都有包含,因此 writer 强制使用管道来划分。

    writer 的引用策略同样是可配置的,能够用的参数如下:
     

    • csv.QUOTE_ALL: 把每列都扩起来,无论是否包含分隔符
    • csv.QUOTE_MINIMAL: 只将包含分隔符的列扩起来
    • csv.QUOTE_NONNUMBERIC: 将所有非数值的列扩起来
    • csv.QUOTE_NONE: 不扩起来。这种方式强制用户检查每列的输入中是否包含分隔符,如果不检测,读取的列数将会是错误的。

    读/写字点数据
     

    我们已经看过了一些基础的读取/生成 CSV 数据的例子,不过在实际环境中,我们并不希望 CSV 文件那么的混乱,我们需要它们给出里边每一个列所表示的意义。
     
    同样,实际环境下我们的数据不一定都是在数组中,我们有的是一些业务模型并且易懂。通常我们会使用字典来达到这个目的,python 相应提供了从 CVS 中读取/生成字典的工具。
     
    代码差不多这个样子:

    [python] view plain copy
     
    1. import csv  
    2.   
    3. dictionaries = [{'age': '30', 'name': 'John', 'last_name': 'Doe'}, {'age': '30', 'name': 'Jane', 'last_name': 'Doe'}]  
    4. with open('my.csv', 'w+') as csv_file:  
    5.     headers = [k for k in dictionaries[0]]  
    6.     writer = csv.DictWriter(csv_file, fieldnames=headers)  
    7.     writer.writeheader()  
    8.     for dictionary in dictionaries:  
    9.         writer.writerow(dictionary)  
    10.   
    11. with open('my.csv', 'r+') as csv_file:  
    12.     reader = csv.DictReader(csv_file)  
    13.     print(str([row for row in reader]))  


    我们用一个数组的测试数据初始化 dictionaries 变量,然后我们打开一个 write 模式的文件,将字典数据中的键集合写入到文件中。首先我们做的就是写键集合,然后再写数组中的字典,一个字典一行。
     
    接下来我们以 read 模式打开同一个文件,获取此文件的 reader,然后将其打印成数组。输出结果如下:

    [python] view plain copy
     
    1. [{'name': 'John', 'age': '30', 'last_name': 'Doe'}, {'name': 'Jane', 'age': '30', 'last_name': 'Doe'}]  


    输出的 CSV 文件如下:

    [python] view plain copy
     
    1. name,last_name,age  
    2. John,Doe,30  
    3. Jane,Doe,30  


    现在它看起来就舒服多了。这个 CSV 文件包含了列信息,每行按照列顺序将数据排列好。注意到我们把属性名字给了 writer,在 python 中字典是无序的,因此在给定的情况下每行的数据顺序将会是之前所指定的。
     
    这种方法同样可以应用到配置了分隔符和引用符的默认 writer 和 reader 上。
     
    同样,我们把代码变的更灵活些:

     

    [python] view plain copy
     
    1. import csv  
    2.   
    3. def read_dict(file_location):  
    4.     with open(file_location, 'r+') as csv_file:  
    5.         reader = csv.DictReader(csv_file)  
    6.         print(str([row for row in reader]))  
    7.         return [row for row in reader]  
    8.   
    9.   
    10. def write_dict(file_location, dictionaries):  
    11.     with open(file_location, 'w+') as csv_file:  
    12.         headers = [k for k in dictionaries[0]]  
    13.         writer = csv.DictWriter(csv_file, fieldnames=headers)  
    14.         writer.writeheader()  
    15.         for dictionary in dictionaries:  
    16.             writer.writerow(dictionary)  
    17.   
    18.   
    19. def dict_test():  
    20.     input_rows = []  
    21.     keep_going = True  
    22.     while keep_going:  
    23.         name = input("Name: ")  
    24.         last_name = input("Last Name: ")  
    25.         age = input("Age: ")  
    26.         input_rows.append({"name": name, "last_name": last_name, "age": age})  
    27.         ui_keep_going = input("continue? (y/N): ")  
    28.         if ui_keep_going != "y":  
    29.             keep_going = False  
    30.   
    31.     print(str(input_rows))  
    32.   
    33.     write_dict('dict.csv', input_rows)  
    34.     written_value = read_dict('dict.csv')  
    35.     print(str(written_value))  
    36.   
    37. dict_test()  

    我们现在运行这个代码,会有如下的结果:

    Name: John
    Last Name: Doe
    Age: 30
    continue? (y/N): y
    Name: Jane
    Last Name: Doe
    Age: 40
    continue? (y/N): 
    [{'age': '30', 'last_name': 'Doe', 'name': 'John'}, {'age': '40', 'last_name': 'Doe', 'name': 'Jane'}]
    [{'age': '30', 'last_name': 'Doe', 'name': 'John'}, {'age': '40', 'last_name': 'Doe', 'name': 'Jane'}]
    


    我们的 dict.csv 内容:

    age,last_name,name
    30,Doe,John
    40,Doe,Jane
    


    一些注意点。就像我之前说过的,在 python 中字典是无序的,所以当你从一个字典中提取键集合并将数据写入到一个 CSV 文件的时候你应该将它们排好序始终使它们保持同样的顺序。你并不知道你的用户会用什么方法来读取这些数据,当然,在实际环境中 CSV 文件总是在增长的,你总是在增加文件的行,而不是覆盖它们。为了避免不必要的麻烦首先就是确保你的 CSV 文件始终看起来相同。

  • 相关阅读:
    路由
    客户端如何调用
    第一个简单的DEMO
    Web API初印象
    项目开发中经常使用的缓存
    EF的Model First
    如何计算代码的运行性能
    使用Obsolete特性来标记方法过时或弃用
    nodeJs实现文件上传,下载,删除
    node 部署教程二
  • 原文地址:https://www.cnblogs.com/nkwy2012/p/8301817.html
Copyright © 2020-2023  润新知