如何正确写入CSV文件?

时间:2018-09-10 15:20:53

标签: python csv

为了提供模型及其存储在db中的数据,我想将其写入csv文件。但是,结果csv文件的第一行顺序不正确。

models.py

class BRANCH():
    ID                  =   db.Column(db.String(6), primary_key=True)
    Branch              =   db.Column(db.String(20))
    Status              =   db.Column(db.String(20))
    Curr                =   db.Column(db.String(5))
    Inputter            =   db.Column(db.String(35))
    Createdon           =   db.Column(db.String(20))
    Authorizer          =   db.Column(db.String(35))
    Authorizeon         =   db.Column(db.String(20))
    Description         =   db.Column(db.String(50))
    LocalDescription    =   db.Column(db.String(50))
    BranchManagerName   =   db.Column(db.String(35))
    LocalBranchManagerName = db.Column(db.String(100))
    ContactNumber       =   db.Column(db.String(35))
    Address             =   db.Column(db.String(100))
    LocalAddress        =   db.Column(db.String(100))
    District            =   db.Column(db.String(9))
    Province            =   db.Column(db.String(3))
    ReportLocked        =   db.Column(db.String(1))
    RegisteredDate      =   db.Column(db.String(20))
    PrevMonthAmount     =   db.Column(db.Numeric(25, 9))
    PrevYearAmount      =   db.Column(db.Numeric(25, 9))

因此,db中的数据存储如下:

 Branch | Status | Curr | Inputter  |      Createdon      | Authorizer |     Authorizeon     | ID  |       Description       | BranchManagerName | ContactNumber |                                         Address                                         | District | Province | ReportLocked | RegisteredDate | PrevYearAmount | PrevMonthAmount | LocalBranchManagerName | LocalDescription |                                LocalAddress                                 
--------+--------+------+-----------+---------------------+------------+---------------------+-----+-------------------------+-------------------+---------------+-----------------------------------------------------------------------------------------+----------+----------+--------------+----------------+----------------+-----------------+------------------------+------------------+-----------------------------------------------------------------------------
 HO     | AUTH   | 9    | MINAL | 2018-09-10 21:48:13 | MORAKOT.V  | 2018-09-10 21:48:13 | HO  | Head Office             | Chariya Sambeth   | N/A           | #3722,  Sihanou Blv, Veal Vonging, 7 Makara, Phnom Penh City.                           |          | 12       | 10000        | 2015-12-16     |    0.000000000 |     0.000000000 | ចរិយាសម្បត្តិ              | ការិយាល័យកណ្តាល     | ផ្ទះលេខ៥៧១ ក្រុមទី.៥ ផ្លូវ៥៧៤ ភូមិក. ឃុំ-សង្កាត់វាលវង់ ក្រុង-ស្រុក-ខណ្ឌ៧មករា ខេត្ត-រាជធានីភ្នំពេញ
 HO     | AUTH   | 6    | MINAL | 2018-09-10 21:49:26 | MORAKOT.V  | 2018-09-10 21:49:26 | KPS | Preah Sihanouk Province | Lipop Heang       | N/A           | Group 1110 Village 1112 Commune 1112 Preah Sihanouk Preah Sihanouk                      |          | 18       | 10000        | 2016-07-28     |    0.000000000 |     0.000000000 | ហៀង លីបផប់               | ខែត្រព្រះសីហនុ       | ក្រុម ១១១០ ភូមិ ០២ សង្កាត់ ១១១២ ខណ្ឌព្រះសីហនុ ខេត្តព្រះសីហនុ
 HO     | AUTH   | 2    | MINAL | 2018-09-10 21:50:58 | MORAKOT.V  | 2018-09-10 21:50:58 | SRP | Siemreap Province       | Vicheka Kong      | NA            | House 222A, Street 222A, Knar Village Chreav Commune Siem Reap City Siem Reap Province. | 1710     | 17       | 10000        | 2017-11-24     |    0.000000000 |     0.000000000 | គង់ វិច្ឆការ              | ខែត្រសៀមរាប       | ផ្ទះលេខ២២២អា,<U+200B>ផ្លូវលេខ<U+200B>២២២អា,<U+200B>ភូមិខ្នារ សង្កាត់ជ្រាវ ក្រុងសៀមរាប ខេត្តសៀមរាប

这是我的脚本,用于将这些数据写入csv文件:

from app.Branch.models import *
from sqlalchemy.orm import aliased

TableName = 'BRANCH'

Columns = BRANCH.__table__.columns.keys()

def writeCSV(ID):
    f= open("%s.csv"%TableName,"a+")

    obj = BRANCH.query.order_by(BRANCH.ID).filter(BRANCH.ID==ID).first()

    string = ''

    # set body data
    for col in Columns:
        try:
            string = string + "," + getattr(obj,col).encode('utf-8')
        except Exception as e:
            print col
            string = string + "," + str(getattr(obj,col))

    f.write(string[1:]+'\n')

    f.close

string = ''

f= open("%s.csv"%TableName,"w+")
# set header
for col_header in Columns:
    string = string + "," + col_header
f.write(string[1:]+'\n')
f.close

branchObj = BRANCH.query.all()

for item in branchObj:
    writeCSV(item.ID)

但是,除了如下所示的第一行之外,最终的csv文件还是可以的:

Branch  Status  Curr    Inputter    Createdon   Authorizer  Authorizeon ID  Description LocalDescription    BranchManagerName   LocalBranchManagerName  ContactNumber   Address LocalAddress    District    Province    ReportLocked    RegisteredDate  PrevMonthAmount PrevYearAmount              
 City.  <!> ផ្ទះលេខ៥៧១ ក្រុមទី.៥ ផ្លូវ៥៧៤ ភូមិក. ឃុំ-សង្កាត់វាលវង់ ក្រុង-ស្រុក-ខណ្ឌ៧មករា ខេត្ត-រាជធានីភ្នំពេញ       12  10000   2015-12-16  0   0                                                                   
HO  AUTH    6   MORAKOT.V   2018-09-10 21:49:26 MORAKOT.V   2018-09-10 21:49:26 KPS Preah Sihanouk Province ខែត្រព្រះសីហនុ  Lipop Heang ហៀង លីបផប់  N/A Group 1110 Village 1112 Commune 1112 Preah Sihanouk Preah Sihanouk  ក្រុម ១១១០ ភូមិ ០២ សង្កាត់ ១១១២ ខណ្ឌព្រះសីហនុ ខេត្តព្រះសីហនុ        18  10000   2016-07-28  0   0               
HO  AUTH    2   MORAKOT.V   2018-09-10 21:50:58 MORAKOT.V   2018-09-10 21:50:58 SRP Siemreap Province   ខែត្រសៀមរាប Vicheka Kong    គង់ វិច្ឆការ    NA  House 222A   Street 222A     Knar Village Chreav Commune Siem Reap City Siem Reap Province. ផ្ទះលេខ២២២អា    ​ផ្លូវលេខ​២២២អា ​ភូមិខ្នារ សង្កាត់ជ្រាវ ក្រុងសៀមរាប ខេត្តសៀមរាប 1710    17  10000   2017-11-24  0   0

数据被截断的位置用<!>标记。

怎么了?我该如何解决?谢谢。

2 个答案:

答案 0 :(得分:2)

我能够使用模拟数据源在本地重现此内容。

看起来您实际上必须关闭文件以确保已刷新。

f.close()   # instead of f.close

您正在2个地方执行此操作;请注意,f.close返回功能,但是f.close()实际上会调用它。可以使用确定性地重现该问题

def writeCSV(ID):

    f= open("%s.csv"%TableName,"a+")

    obj = BRANCH.query.order_by(BRANCH.ID).filter(BRANCH.ID==ID).first()

    string = ''

    # set body data
    for col in Columns:
        try:
            string = string + "," + getattr(obj,col).encode('utf-8')
        except Exception as e:
            print col
            string = string + "," + str(getattr(obj,col))

    f.write(string[1:]+'\n')
    f.close()
    if ID == 0:
        # here we simulate what would happen if the GC decides
        # to release the first open handle at this point
        g.close()

string = ''

g= open("%s.csv"%TableName,"w+")  # note the rename for demonstration purposes
# set header
for col_header in Columns:
    string = string + "," + col_header
g.write(string[1:]+'\n')
g.close

branchObj = BRANCH.query.all()

for item in branchObj:
    writeCSV(item.ID)

如果不显式调用close,则将其留给GC来决定何时应关闭文件,这可能会导致此类错误。参见http://blog.lerner.co.il/dont-use-python-close-files-answer-depends/

相关说明:考虑一次打开文件 ,并将f传递到writeCSV中使用,而不是在writeCSV内部打开文件。此外,考虑使用with语法:

with open("%s.csv"%TableName,"w+") as f:
    writeHeader(f)
    for item in branchObj:
        writeCSV(f, item.id)

这样,可以确保您以序列化方式使用一个输出流,并且with会在文件退出后立即将其关闭。

答案 1 :(得分:-1)

请改用内置CSV模块。 这是一个例子。

#!/usr/bin/env python3
import csv

导入inbuilt CSV module。您可以参考文档进行调整。

sample = [("Branch", "Status" ,"Curr"), ("HO","AUTH"), ("HO","AUTH",9)]

类似于您的数据的样本输入。让我们将第一个元组视为标头。

csv.register_dialect(
            'test', 'unix', delimiter=' ', quoting=csv.QUOTE_NONNUMERIC,
            skipinitialspace=True
        )
test_dialect = csv.get_dialect('test')

在这里,我们正在创建一个名为“ test”的自定义方言。我们将分隔符指定为一个空格。

现在让我们打开一个文件并将数据写入其中。在with子句中打开文件将自动关闭它。 在这里,我们将创建一个csv.writer对象,即testwriter,将方言作为我们的自定义test_dialect。 testwriter.writerow()将从元组中写出整行,并以空格作为定界符。

filename = "test.csv"
with open(filename, 'w', newline='') as csvfile:
            testwriter = csv.writer(csvfile, test_dialect)
            for datas in sample:
                testwriter.writerow(datas)

test.csv文件如下,

"Branch" "Status" "Curr"
"HO" "AUTH"
"HO" "AUTH" 9