Python 如何从csv中读取多行

Python 如何从csv中读取多行,python,csv,list-comprehension,Python,Csv,List Comprehension,我有一个csv文件,其中包括姓名和电话号码。我只对一个名字感兴趣,只要我有它的电话号码 with open(phone_numbers) as f: reader = csv.DictReader(f) names = [record['Name'] for record in reader if record['phone']] 但我也想要相应的电话号码,我尝试过: user_data = {} with open(phone_numbers) as f: read

我有一个csv文件,其中包括姓名和电话号码。我只对一个名字感兴趣,只要我有它的电话号码

with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    names =  [record['Name'] for record in reader if record['phone']]
但我也想要相应的电话号码,我尝试过:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'] =  [record['Name'] for record in reader if record['phone']]
    user_data['phone'] = [record['phone'] for record in reader if record['phone']]
user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'],user_data['phone'] =  [(record['Name'],record['phone']) for record in reader if record['phone']]
但是对于第二项,我得到了一个空字符串,我猜
record
是一个生成器,这就是为什么我可以迭代它两次

我曾尝试使用元组,但仅以这种方式工作:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'] =  [(record['Name'],record['phone']) for record in reader if record['phone']]
在这种情况下,我有两个变量,
phone
Name
存储在
user\u data['Name']
中,这不是我想要的

如果我试试这个:

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'] =  [record['Name'] for record in reader if record['phone']]
    user_data['phone'] = [record['phone'] for record in reader if record['phone']]
user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data['Name'],user_data['phone'] =  [(record['Name'],record['phone']) for record in reader if record['phone']]
我得到了以下错误:

ValueError:要解压缩的值太多

编辑:

这是表格的一个示例:

+--------+---------------+
|电话号码|
+--------+---------------+
|路易斯| 000 111 22222 |
+--------+---------------+
|保罗| 000 222 3333 |
+--------+---------------+
|安德里亚| |
+--------+---------------+
|豪尔赫| 111 222 3333 |
+--------+---------------+


所以所有的行都有一个名字,但不是所有的行都有电话。

你猜得很对。如果这是您希望采用的方法-迭代两次,则应使用
seek(0)

但是,这不是很有效,您应该尝试一次性获取数据。以下各项应一次性完成:

user_data = {}

def extract_user(user_data, record):
    if record['phone']:
        name = record.pop('name')
        user_data.update({name: record})

[extract_user(user_data, record) for record in reader]
例如:

In [20]: cat phones.csv
name,phone
hans,01768209213
grettel,
henzel,123457123

In [21]: f = open('phones.csv')

In [22]: reader = csv.DictReader(f)

In [24]: %paste
user_data = {}

def extract_user(user_data, record):
    if record['phone']:
        name = record.pop('name')
        user_data.update({name: record})

[extract_user(user_data, record) for record in reader]

## -- End pasted text --
Out[24]: [None, None, None]

In [25]: user_data
Out[25]: {'hans': {'phone': '01768209213'}, 'henzel': {'phone': '123457123'}}

我认为有一种更简单的方法,因为它是一个csv文件,因为有列标题,如您所示,然后每行中都有一个phone值,它要么是空的,要么是什么-因此此测试不做任何测试,如果不是空的,则将名称和phone添加到用户_数据中

import csv
user_data = []
with open(f,'rb') as fh:
   my_reader = csv.DictReader(fh)
   for row in my_reader:
       if row['phone'] != ''
           user_details = dict()
           user_details['Name'] = row['Name']
           user_details['phone'] = row['phone']
           user_data.append(user_details)
通过使用DictReader,我们让魔法发生,所以我们不必担心seek等问题

如果我不懂,而你想要一本字典,那就很容易了

import csv
user_data = dict()
with open(f,'rb') as fh:
   my_reader = csv.DictReader(fh)
   for row in my_reader:
       if row['phone'] != ''
           user_data['Name'] = row['phone']

有没有可能您正在寻找的是丢弃数据文件中的一些信息

In [26]: !cat data00.csv
Name,Phone,Address
goofey,,ade
mickey,1212,heaven
tip,3231,earth

In [27]: f = open('data00.csv')

In [28]: r = csv.DictReader(f)

In [29]: lod = [{'Name':rec['Name'], 'Phone':rec['Phone']} for rec in r if rec['Phone']]

In [30]: lod
Out[30]: [{'Name': 'mickey', 'Phone': '1212'}, {'Name': 'tip', 'Phone': '3231'}]

In [31]: 
另一方面,如果您的文件只包含
Name
Phone
列,则 只是


您可以使用
dict
将元组列表转换为字典。此外,如果您的记录没有
phone
值,则需要使用
get

import csv

user_data = {}
with open(phone_numbers) as f:
    reader = csv.DictReader(f)
    user_data = dict([(record['Name'], record['phone']) for record in reader if record.get('phone').strip())
如果要分别列出
name
s和
phone
s,可以使用
*
表达式


我通常使用行索引:

input = open('mycsv.csv', 'r')
user_data = {}

for row in csv.reader(input):
    if row[<row # containing phone>]:
        name = row[<row # containing name>]
        user_data[name] = row[<row # containing phone>]
input=open('mycsv.csv','r')
用户_数据={}
对于csv.reader中的行(输入):
如果第[]行:
名称=行[]
用户_数据[名称]=行[]

除了打开包装外,您在整个过程中都是正确的

result = [(record["name"], record["phone"]) for record in reader if record["phone"]]
# this gives [(name1, phone1), (name2,phone2),....]

您必须执行
[dostuff for name,phone in result]
而不是
name,phone=result
,这在语义和语法上都没有意义

尝试
zip(*)
转换最后一行中的列表。检查此答案。您可以澄清您的数据是一列还是多列,如果多列是同一行中的电话号码和姓名吗?我想您是在表明电话和姓名在同一行中row@PyNEwbie它是多列的,所有行都有名称,但不是所有行都有电话号码,这是我在使用if record['phone']时的方式。我不确定这是否是问题所在-最后一个块会重新打开文件。问题在于解包。OP想要一个字典作为最终结果,你的构造将给他一个字典列表谢谢我仍然不清楚,但两个选项都会work@PyNEwbie我尝试了你的第二个密码,我有一个电话号码分配给一个名字,但我想与姓名和电话,如果电话存在。出于某种原因,我只得到一行的值,文件有几行。@Luis得到一行的值可能是因为python dict不支持重复键-最后一行获胜。如果你需要重复的钥匙,这里有可能的解决办法:谢谢,两个都有效。dict方法是否适用于两个以上的项目?它还将第一个值作为键,这意味着如果有重复的值,它将被破坏?@是的,它将适用于两个以上的项目。如果文件中有重复的
名称
,则不会中断,但只保留最后一个值。如果您有一个重复的键,我的意思是
name
最好的方法是将结果保存为
元组的列表。顺便说一句,这就是使用的
tuple
。如果答案有帮助,也不要忘记接受。
result = [(record["name"], record["phone"]) for record in reader if record["phone"]]
# this gives [(name1, phone1), (name2,phone2),....]