python - 如何将 yaml.load_all 与 fileinput.input 一起使用?

标签 python pyyaml

在不求助于 ''.join 的情况下,是否有一种 Pythonic 方式将 PyYAML 的 yaml.load_allfileinput.input() 一起用于轻松流式传输来自多个来源的多个文档?

我正在寻找类似以下内容的内容(非工作示例):

# example.py
import fileinput

import yaml

for doc in yaml.load_all(fileinput.input()):
    print(doc)

预期输出:

$ cat >pre.yaml <<<'--- prefix-doc'
$ cat >post.yaml <<<'--- postfix-doc'
$ python example.py pre.yaml - post.yaml <<<'--- hello'
prefix-doc
hello
postfix-doc

当然,yaml.load_all 需要字符串、字节或类似文件的对象,而 fileinput.input() 不是这些,所以上面的例子不起作用。

实际输出:

$ python example.py pre.yaml - post.yaml <<<'--- hello'
...
AttributeError: FileInput instance has no attribute 'read'

您可以使示例与 ''.join 一起工作,但那是作弊。我正在寻找一种不会立即将整个流读入内存的方法。

我们可以将问题改写为是否有某种方法可以模拟字符串、字节或类似文件的对象来代理字符串的底层迭代器?但是,我怀疑 yaml .load_all 实际上需要整个类似文件的界面,因此措辞会要求比绝对必要的更多。

理想情况下,我正在寻找能够支持如下内容的最小适配器:

for doc in yaml.load_all(minimal_adapter(fileinput.input())):
    print(doc)

最佳答案

fileinput.input 的问题是生成的对象没有 read 方法,而 yaml.load_all 是寻找。如果您愿意放弃 fileinput,您可以编写自己的类来执行您想要的操作:

import sys                                                                      
import yaml                                                                     

class BunchOFiles (object):                                                     
    def __init__(self, *files):                                                 
        self.files = files                                                      
        self.fditer = self._fditer()                                            
        self.fd = self.fditer.next()                                            

    def _fditer(self):                                                          
        for fn in self.files:                                                   
            with sys.stdin if fn == '-' else open(fn, 'r') as fd:               
                yield fd                                                        

    def read(self, size=-1):                                                    
        while True:                                                             
            data = self.fd.read(size)                                           

            if data:                                                            
                break                                                           
            else:                                                               
                try:                                                            
                    self.fd = self.fditer.next()                                
                except StopIteration:                                           
                    self.fd = None                                              
                    break                                                       

        return data                                                             

bunch = BunchOFiles(*sys.argv[1:])                                              
for doc in yaml.load_all(bunch):                                                
    print doc                                                                   

BunchOFiles 类为您提供了一个带有 read 方法的对象,该方法会愉快地遍历文件列表,直到所有内容都用完。鉴于上述代码和您的样本输入,我们得到了您正在寻找的输出。

关于python - 如何将 yaml.load_all 与 fileinput.input 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39359390/

相关文章:

python - 如何将数据附加到 YAML 文件

python - 在 PyObjC 中监听 onclick 事件

Python Excel 运行宏到 xlsx 文件

python - 如何从python访问和修改yaml文件的内容?

python - PyYAML 错误 : "yaml.scanner.ScannerError: mapping values are not allowed here"

python - 如何处理 PyYaml 中的标签/类向后兼容性?

python - 如何使用 Python 读取自定义序列化 YAML 对象(由 Rails 编写)?

python - 如何将嵌套字典转换为数据框?

python - 如何使用 Python 的 scipy.integrate.quad 评估多元函数的单积分?

Python Plotly - 离线图表嵌入到 HTML 中(不工作)