带百分比的Python字符串格式(“TypeError:格式字符串”的参数不足)

带百分比的Python字符串格式(“TypeError:格式字符串”的参数不足),python,python-3.x,Python,Python 3.x,以下代码无法运行 它遍历CSV文件,检索值并将其格式化为元组数组(插入查询),以供以后使用。 问题是csv的最后一列有时是字符串或无(如下面的csv示例所示)。 错误如下。 有人能帮我吗 def csv_to_DB(csv_输入): 打开(csv_输入,换行符=“”)作为csvfile: csv_data=csv.reader(csvfile,分隔符=',',引号=') to_insert=[]将是元组列表 insert_str=“插入表(ID、用户、用户版本、值、说明)值” template=

以下代码无法运行

它遍历CSV文件,检索值并将其格式化为元组数组(插入查询),以供以后使用。 问题是csv的最后一列有时是字符串或无(如下面的csv示例所示)。 错误如下。 有人能帮我吗

def csv_to_DB(csv_输入):
打开(csv_输入,换行符=“”)作为csvfile:
csv_data=csv.reader(csvfile,分隔符=',',引号=')
to_insert=[]将是元组列表
insert_str=“插入表(ID、用户、用户版本、值、说明)值”
template=“('%s','%s','%s','%s','%s','%s')”
对于csv_数据中的行:
to_insert.append(tuple(row))将行/列表转换为tuple并将其添加到列表
query=insert_str+'\n'。加入(模板%to_insert)
#将查询用于其他操作。。。
CSV示例:

1,aaa,1,0.0,
2,bbb,1,0.13,
3,ccc,1,0.0,
4,ddd,3,1.0,Rom
5,eee,1,0.08,
错误:

    query = insert_str + '\n'.join(template % to_insert)
TypeError: not enough arguments for format string
注:此问题是对

更新

澄清:目标是创建一个具有多个值的插入,而不是多个插入。在这种情况下:

INSERT INTO table (ID, user, user_version, value, description) VALUES 
('1', 'aaa', '1', '0.0', ''), 
('2', 'bbb', '1', '0.13', ''), 
('3', 'ccc', '1', '0.0', ''), 
('4', 'ddd', '3', '1.0', 'Rom'), 
('5', 'eee', '1', '0.08', '')
插入的
将是:

[('1', 'aaa', '1', '0.0', ''), ('2', 'bbb', '1', '0.13', ''), ('3', 'ccc', '1', '0.0', ''), ('4', 'ddd', '3', '1.0', 'Rom'), ('5', 'eee', '1', '0.08', '')]
template=“('%s','%s','%s','%s','%s','%s')”
-五个参数

但您使用:

1,aaa,1,0.0,
-4个参数(错误

2,bbb,1,0.13,
-5个参数(OK

3,ccc,1,0.0,
-4个参数(错误

4,ddd,3,1.0,Rom
-5个参数(OK


5,eee,1,0.08,
-4个参数(错误

您的问题在于此表达式:

(template % to_insert)
模板需要5个参数,并且插入的
始终为1!,因为它是一个列表,所以它被视为单个参数

更改为_insert
更改为
tuple(to _insert)
并将查询移出循环将解决您的问题,这取决于您尝试获取的内容

尝试将循环更改为以下内容:

for row in csv_data:
    to_insert.append(tuple(row)) # convert row/list to tuple and add it to list
query = insert_str + '\n'.join(template % tuple(to_insert))
更新:根据@JonyD的更新,模板是不必要的,因为它强制您设置5行。此外,您希望将列表而不是字符串传递给
join()
。您应该做的是:

def csv_to_DB(csv_input):
    with open(csv_input, newline='') as csvfile:
        csv_data = csv.reader(csvfile, delimiter=',', quotechar='"')
        to_insert = [] # will be list of tuples
        insert_str="INSERT INTO table (ID, user, user_version, value, description) VALUES"

        for row in csv_data:
            to_insert.append(tuple(row)) # convert row/list to tuple and add it to list
        query = insert_str + '\n'.join(to_insert) 

只需简单的字符串添加即可获得所需的输出,无需字符串模板:

def xing_csv_to_crmDB2(csv_input):
    query = ''
    with open(csv_input, 'r', newline='') as csvfile:
        csv_data = csv.reader(csvfile, delimiter=',', quotechar='"')
        insert_str = "INSERT INTO table (ID, user, user_version, value, description) VALUES "

        for row in csv_data:
            query += '\n' + str(tuple(row))
        insert_str += query
# do something
这将产生以下输出:

INSERT INTO table (ID, user, user_version, value, description) VALUES
('1', 'aaa', '1', '0.0', '')
('2', 'bbb', '1', '0.13', '')
('3', 'ccc', '1', '0.0', '')
('4', 'ddd', '3', '1.0', 'Rom')
('5', 'eee', '1', '0.08', '')

更新: 根据@Tomerikoo的想法,一个更加简化的版本:

def xing_csv_to_crmDB2(csv_input):
    with open(csv_input, 'r', newline='') as csvfile:
        csv_data = csv.reader(csvfile, delimiter=',', quotechar='"')
        insert_str = "INSERT INTO table (ID, user, user_version, value, description) VALUES "

        for row in csv_data:
            insert_str += '\n' + str(tuple(row))
# do something

输出仍然是一样的。

这是我想要的答案。请随意使用。它非常快。 要在RDS mysql中插入380万条记录,当
bloc_size=10000时需要2分钟

def csv2mysql(csv_输入,db_选项,插入_配置,block_size='1000'):
"""
:param csv_input:输入csv文件路径
:param db_opts:是一个字典。应如以下示例所示:
tvnow_db_opts={
“用户”:db_conn.login,
“密码”:db_conn.password,
“主机”:db_conn.host,
“数据库”:db_conn.schema
}
:param insert_conf:请参见下面的说明
插入_conf={
“表格名称”:“我的表格”,
“列”:“ID、字段1、字段2、字段3、字段4”,
‘值模板’:“('%s','%s','%s','%s','%s','%s','%s')”
}
table_name:插入数据的DB表名
列:csv对应的列;用逗号分隔。
示例:“ID,字段1,字段2,字段3,字段4”
值\u模板:字符串格式为“(“%s”、“s”、“s”、“s”、“s”、“s”)。“%s”的数量必须与表中csv/列中的字段数量相同
:param block_size:每个sql insert命令插入的行/记录数。默认值1000
"""
打印(“将csv文件{}插入数据库{}”。格式(csv_输入,db_选择['host']))
conn=pymysql.connect(**db_opts)
cur=连接光标()
尝试:
打开(csv_输入,换行符=“”)作为csvfile:
csv_data=csv.reader(csvfile,分隔符=',',引号=')
to_insert=[]将是元组列表
insert_str=“insert INTO{}({})VALUES”。格式(insert_conf.table_name,insert_conf.columns)
计数=0
对于csv_数据中的行:
计数+=1
to_insert.append(tuple(row))将行/列表转换为tuple并将其添加到列表
如果计数%block_size==0:
query=insert_str+',\n'。加入([insert_conf.values_template%r for r in to_insert])
当前执行(查询)
插入=[]
康涅狄格州提交
#提交/插入其余行
如果len(to_insert)>0:
query=insert_str+',\n'。加入([insert_conf.values_template%r for r in to_insert])
当前执行(查询)
康涅狄格州提交
最后:
康涅狄格州关闭
打印('已完成将csv文件插入数据库')

有些东西与此不符。取消记录查询分配或在join函数中使用元组(行)。您的模板与所有行相关,还是与单个行相关@JonyD@SukumarRdjf我不认为这是问题所在,因为错误是没有足够的参数。我相信这个错误是在第一次迭代时抛出的,我想这就是问题所在。在每次迭代中创建查询变量时,一旦插入的
变量的长度不是
5
,它就会抛出错误,因为
模板中只有
5%s
%s
的数量应等于
to_insert
变量的长度。@SukumarRdjf这并不完全准确,因为
to_insert
是一个列表,它被视为一个参数。不管它有多长@JonyD你能给出一个想要的ou的准确例子吗