我尝试从python中的 HDFS 导入文件列表。
如何通过HDFS执行此操作:
path =r'/my_path'
allFiles = glob.glob(path + "/*.csv")
df_list = []
for file_ in allFiles:
df = pd.read_csv(file_,index_col=None, header=0,sep=';')
df_list.append(df)
我认为 subprocess.Popen 可以解决问题,但如何仅提取文件名?
import subprocess
p = subprocess.Popen("hdfs dfs -ls /my_path/ ",
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print(line)
输出如下:
b'Found 32 items\n'
b'-rw------- 3 user hdfs 42202621 2019-01-21 10:05 /my_path/file1.csv\n'
b'-rw------- 3 user hdfs 99320020 2019-01-21 10:05 /my_path/file2.csv\n'
答案 0 :(得分:1)
免责声明:这将是漫长而乏味的。但是在这种情况下,我将尝试使其尽可能通用和可复制。
考虑到没有外部库(pandas
除外)的要求,没有选择的余地。我建议尽可能利用WebHDFS
。
AFAIK, HDFS 的默认安装包括 WebHDFS 的安装。以下解决方案严重依赖 WebHDFS 。
首先,您必须了解 WebHDFS 网址。 WebHDFS 安装在 HDFS名称节点上,默认端口为 50070 。
因此,我们从http://[namenode_ip]:50070/webhdfs/v1/
开始,其中/webhdfs/v1
/是所有人的通用网址。
为了举例,我们将其假设为http://192.168.10.1:50070/web/hdfs/v1
。
通常,人们可以使用curl
列出HDFS目录的内容。
有关详细说明,请参阅WebHDFS REST API: List a Directory
如果要使用curl
,则以下提供FileStatuses
给定目录内的所有文件。
curl "http://192.168.10.1:50070/webhdfs/v1/<PATH>?op=LISTSTATUS"
^^^^^^^^^^^^ ^^^^^ ^^^^ ^^^^^^^^^^^^^
Namenode IP Port Path Operation
如前所述,这将在JSON对象中返回FileStatuses:
{
"FileStatuses":
{
"FileStatus":
[
{
"accessTime" : 1320171722771,
"blockSize" : 33554432,
"group" : "supergroup",
"length" : 24930,
"modificationTime": 1320171722771,
"owner" : "webuser",
"pathSuffix" : "a.patch",
"permission" : "644",
"replication" : 1,
"type" : "FILE"
},
{
"accessTime" : 0,
"blockSize" : 0,
"group" : "supergroup",
"length" : 0,
"modificationTime": 1320895981256,
"owner" : "szetszwo",
"pathSuffix" : "bar",
"permission" : "711",
"replication" : 0,
"type" : "DIRECTORY"
},
...
]
}
}
使用python的默认库可以实现相同的结果:
import requests
my_path = '/my_path/'
curl = requests.get('http://192.168.10.1:50070/webhdfs/v1/%s?op=LISTSTATUS' % my_path)
并且如上所述,每个文件的实际状态比结果JSON低两个级别。换句话说,要获取每个文件的FileStatus:
curl.json()['FileStatuses']['FileStatus']
[
{
"accessTime" : 1320171722771,
"blockSize" : 33554432,
"group" : "supergroup",
"length" : 24930,
"modificationTime": 1320171722771,
"owner" : "webuser",
"pathSuffix" : "a.patch",
"permission" : "644",
"replication" : 1,
"type" : "FILE"
},
{
"accessTime" : 0,
"blockSize" : 0,
"group" : "supergroup",
"length" : 0,
"modificationTime": 1320895981256,
"owner" : "szetszwo",
"pathSuffix" : "bar",
"permission" : "711",
"replication" : 0,
"type" : "DIRECTORY"
},
...
]
由于您现在拥有所需的所有信息,因此您需要做的就是解析。
import os
file_paths = []
for file_status in curl.json()['FileStatuses']['FileStatus']:
file_name = file_status['pathSuffix']
# this is the file name in the queried directory
if file_name.endswith('.csv'):
# if statement is only required if the directory contains unwanted files (i.e. non-csvs).
file_paths.append(os.path.join(path, file_name))
# os.path.join asserts your result consists of absolute path
file_paths
['/my_path/file1.csv',
'/my_path/file2.csv',
...]
现在您知道文件和WebHDFS链接的路径,pandas.read_csv
可以处理其余工作。
import pandas as pd
dfs = []
web_url = "http://192.168.10.1:50070/webhdfs/v1/%s?op=OPEN"
# ^^^^^^^
# Operation is now OPEN
for file_path in file_paths:
file_url = web_url % file_path
# http://192.168.10.1:50070/webhdfs/v1/my_path/file1.csv?op=OPEN
dfs.append(pd.read_csv(file_url))
然后将所有.csv
导入并分配给dfs
。
如果您的HDFS配置为 HA (高可用性),则将有多个 namenodes ,因此必须相应地设置namenode_ip
:活动节点的IP。