【问题标题】:having trouble reading tab separated value txt file in python在 python 中读取制表符分隔值 txt 文件时遇到问题
【发布时间】:2022-01-04 02:09:08
【问题描述】:

我正在尝试读取从 AWS 存储中提取的 python 中的制表符分隔值 txt 文件。 (使用 XXX 审查 AWS 的凭据)

import io
import pandas as pd
import boto3
import csv
from bioservices import UniProt
from sqlalchemy import create_engine
s3 = boto3.resource(
    service_name='s3',
    region_name='us-east-2',
    aws_access_key_id='XXX',
    aws_secret_access_key='XXX'
)

这只是为了连接到 AWS。接下来,当我运行此代码以读取存储在 AWS 中的制表符分隔的 txt 文件时

txt = s3.Bucket('compound-bioactivity-original-files').Object('helper-files/kinhub_human_kinase_list_30092021.txt').get()
txt_reader = csv.reader(txt, delimiter='\t')
for line in txt_reader:
    print(line)

我得到的输出不是我想要的。并且使用 dialect='excel-tab' 而不是 delimiter='\t' 也会给我相同的输出

['ResponseMetadata']
['AcceptRanges']
['LastModified']
['ContentLength']
['ETag']
['VersionId']
['ContentType']
['Metadata']
['Body']

【问题讨论】:

  • 如何检测带有\n\br 的行,然后使用\t 分隔符对其进行迭代,然后将给定的行彼此附加到数组或数据框中?
  • 旁注: 将凭据存储在源代码中通常是不好的做法。相反,使用 AWS CLI aws configure 命令将 AWS 凭证存储在凭证文件中,boto3 会自动找到它们。

标签: python python-3.x amazon-web-services


【解决方案1】:

您的代码有几个问题。

首先,Object.get() 不返回 Amazon S3 对象的内容。相反,根据Object.get() documentation,它返回:

{
    'Body': StreamingBody(),
    'AcceptRanges': 'string',
    'LastModified': datetime(2015, 1, 1),
    'ContentLength': 123,
    'ETag': 'string',
    'VersionId': 'string',
    'CacheControl': 'string',
    'ContentDisposition': 'string',
    ...
    'BucketKeyEnabled': True|False,
    'TagCount': 123,
}

您可以通过插入print(txt) 作为调试行来查看这种情况。

如果你想访问对象的内容,你可以使用Body 元素。要检索流式正文的内容,您可以使用.read()

但是,这会以二进制字符串的形式返回,因为该对象被视为二进制文件。在 Python 中,您可以使用 .decode('ascii') 将其转换回 ASCII。见:How to convert 'binary string' to normal string in Python3?

因此,您实际上需要使用:

txt = s3.Bucket('bucketname').Object('object.txt').get()['Body'].read().decode('ascii')

(如果这看起来太复杂,那么您可以简单地将文件下载到本地磁盘,然后在文件上使用 CSV 阅读器——它会很好地工作而无需使用 get/read/decode。)

下一个问题是documentation for csv.reader 说:

csv.reader(csvfile, dialect='excel', **fmtparams)
返回一个读取器对象,它将遍历给定 csvfile 中的行。 csvfile 可以是任何支持迭代器协议的对象,并在每次调用其 next() 方法时返回一个字符串

由于decode() 命令返回一个字符串,那么for 循环将遍历字符串中的单个字符不会字符串中的行。

坦率地说,您可以在不使用 CSV 阅读器的情况下处理这些行,只需拆分行和选项卡,如下所示:

import boto3

s3 = boto3.resource('s3')

txt = s3.Bucket('bucketname').Object('object.txt').get()['Body'].read().decode('ascii')

lines = txt.split('\n')

for line in lines:
    fields = line.split('\t')
    print(fields)

通过添加一些调试来查看每个步骤是否返回了您期望的数据,例如在每个步骤之后打印变量的内容,上述所有问题应该已经很明显了。

【讨论】:

  • 谢谢你。我是初学者,这很有帮助
猜你喜欢
  • 1970-01-01
  • 2020-04-21
  • 2019-02-21
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多