使用python从HDFS获取文件名列表

时间:2015-09-03 17:26:15

标签: python hadoop

Hadoop noob在这里。

我已经搜索了一些有关hadoop和python入门的教程,但没有取得多大成功。我还不需要对映射器和缩减器进行任何操作,但它更多的是访问问题。

作为Hadoop集群的一部分, HDFS上有一堆.dat文件。

为了使用Python访问我的客户端(本地计算机)上的那些文件,

  

我需要在计算机上安装什么?

     

如何在HDFS上查询文件名?

任何链接也会有所帮助。

5 个答案:

答案 0 :(得分:3)

  

我需要在计算机上安装什么?

你需要安装和运行Hadoop,以及Python。

  

如何在HDFS上查询文件名?

你可以在这里尝试这样的事情。我还没有对代码进行测试,所以不要只依赖它。

request.form['fred']

您还可以查看Pydoop这是Hadoop的Python API。

虽然我的示例包含from subprocess import Popen, PIPE process = Popen('hdfs dfs -cat filename.dat',shell=True,stdout=PIPE, stderr=PIPE) std_out, std_err = process.communicate() check for returncode, std_err if: everything is OK, do whatever with stdout else: do something in else condition ,但您可以尝试在没有它的情况下运行,因为它存在安全风险。 Why you shouldn't use shell=True?

答案 1 :(得分:3)

据我所知,没有开箱即用的解决方案,而且我发现的大多数答案都使用了对hdfs命令的调用。我在Linux上运行,并遇到同样的挑战。我发现sh包非常有用。这会处理为您运行o / s命令并管理stdin / out / err。

有关详细信息,请参阅此处:https://amoffat.github.io/sh/

不是最好的解决方案,但它是一行(ish)并使用标准包。

这是我删除HDFS目录列表的简化代码。它会列出文件和文件夹,因此如果您需要区分它们,可能需要修改它们。

import sh
hdfsdir = '/somedirectory'
filelist = [ line.rsplit(None,1)[-1] for line in sh.hdfs('dfs','-ls',hdfsdir).split('\n') if len(line.rsplit(None,1))][1:]

我的输出 - 在这种情况下,这些都是目录:

[u'/somedirectory/transaction_basket_fct/date_id=2015-01-01',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-02',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-03',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-04',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-05',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-06',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-07',
 u'/somedirectory/transaction_basket_fct/date_id=2015-01-08']

让我们分解一下:

要运行hdfs dfs -ls /somedirectory命令,我们可以像这样使用sh包:

import sh
sh.hdfs('dfs','-ls',hdfsdir)

sh允许您无缝地调用o / s命令,就好像它们是模块上的函数一样。您将命令参数作为函数参数传递。真的很整洁。

对我来说,这会返回类似的内容:

Found 366 items
drwxrwx---+  - impala hive          0 2016-05-10 13:52 /somedirectory/transaction_basket_fct/date_id=2015-01-01
drwxrwx---+  - impala hive          0 2016-05-10 13:52 /somedirectory/transaction_basket_fct/date_id=2015-01-02
drwxrwx---+  - impala hive          0 2016-05-10 13:52 /somedirectory/transaction_basket_fct/date_id=2015-01-03
drwxrwx---+  - impala hive          0 2016-05-10 13:52 /somedirectory/transaction_basket_fct/date_id=2015-01-04
drwxrwx---+  - impala hive          0 2016-05-10 13:52 /somedirectory/transaction_basket_fct/date_id=2015-01-05

使用.split('\n')

将其拆分为基于换行符的行

使用line.rsplit(None,1)[-1]获取字符串中的最后一个'word'。

要防止列表中的空元素出现问题,请使用if len(line.rsplit(None,1))

最后使用Found 366 items

删除列表中的第一个元素([1:]

答案 2 :(得分:2)

您应该拥有群集中节点的登录访问权限。让集群管理员选择节点并设置帐户,并告知您如何安全地访问节点。如果您是管理员,请告诉我集群是本地还是远程,如果是远程,那么它是托管在您的计算机上,公司内部还是第三方云上,如果是,那么我可以提供更多相关信息。< / p>

要在HDFS中查询文件名,请登录到群集节点并运行hadoop fs -ls [path]路径是可选的,如果未提供,则会列出主目录中的文件。如果-R作为选项提供,则它会以递归方式列出路径中的所有文件。此命令还有其他选项。有关此命令和其他Hadoop文件系统shell命令的更多信息,请参阅http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/FileSystemShell.html

在Python中查询HDFS文件名的一种简单方法是使用esutil.hdfs.ls(hdfs_url='', recurse=False, full=False),它在子进程中执行hadoop fs -ls hdfs_url,此外它还具有许多其他Hadoop文件系统shell命令的功能(请参阅来源http://code.google.com/p/esutil/source/browse/trunk/esutil/hdfs.py)。 esutil 可以与pip install esutil一起安装。它位于https://pypi.python.org/pypi/esutil的PyPI上,其文档位于http://code.google.com/p/esutil/,其GitHub网站为https://github.com/esheldon/esutil

答案 3 :(得分:1)

仅使用python 3的原始子进程库来“查询HDFS上的文件名”

from subprocess import Popen, PIPE
hdfs_path = '/path/to/the/designated/folder'
process = Popen(f'hdfs dfs -ls -h {hdfs_path}', shell=True, stdout=PIPE, stderr=PIPE)
std_out, std_err = process.communicate()
list_of_file_names = [fn.split(' ')[-1].split('/')[-1] for fn in std_out.decode().split('\n')[1:]][:-1]
list_of_file_names_with_full_address = [fn.split(' ')[-1] for fn in std_out.decode().split('\n')[1:]][:-1]

答案 4 :(得分:0)

正如JGC所说,您可以做的最直接的事情是首先登录(通过ssh)节点之一(参与Hadoop集群的服务器)并验证您是否具有正确的访问权限控制和特权:

  • 使用HDFS客户端列出您的主目录,即hdfs dfs -ls
  • 列出位于HDFS中的目标目录,即hdfs dfs -ls <absolute or relative path to HDFS directory>

然后,在Python中,您应该使用子进程和HDFS客户端访问感兴趣的路径,并使用-C标志排除不必要的元数据(以避免以后进行丑陋的后处理)。

Popen(['hdfs', 'dfs', '-ls', '-C', dirname])

然后,将输出分成新行,然后将获得路径列表。

以下是有关日志记录和错误处理的示例(包括目录/文件不存在时的示例):

from subprocess import Popen, PIPE
import logging
logger = logging.getLogger(__name__)

FAILED_TO_LIST_DIRECTORY_MSG = 'No such file or directory'

class HdfsException(Exception):
    pass

def hdfs_ls(dirname):
    """Returns list of HDFS directory entries."""
    logger.info('Listing HDFS directory ' + dirname)
    proc = Popen(['hdfs', 'dfs', '-ls', '-C', dirname], stdout=PIPE, stderr=PIPE)
    (out, err) = proc.communicate()
    if out:
        logger.debug('stdout:\n' + out)
    if proc.returncode != 0:
        errmsg = 'Failed to list HDFS directory "' + dirname + '", return code ' + str(proc.returncode)
        logger.error(errmsg)
        logger.error(err)
        if not FAILED_TO_LIST_DIRECTORY_MSG in err:
            raise HdfsException(errmsg)
        return []
    elif err:
        logger.debug('stderr:\n' + err)
    return out.splitlines()

# dat_files will contain a proper Python list of the paths to the '.dat' files you mentioned above.
dat_files = hdfs_ls('/hdfs-dir-with-dat-files/')
相关问题