如何读取通过追加行来不断更新的文件?

2024-10-01 13:33:00 发布

您现在位置:Python中文网/ 问答频道 /正文

在我的终端上我正在运行:

curl --user dhelm:12345 \https://stream.twitter.com/1.1/statuses/sample.json > raw-data.txt

curl的输出是实时流式Twitter数据,这些数据被写入原始文件-数据.txt在

在python中

^{pr2}$

我正在用python读取该文件,并使用json解码器将结果附加到posts中。在

现在,问题是我不想让我的程序在python脚本到达文件末尾时结束。相反,我想在终端上运行的curl向raw文件追加更多post时继续阅读-数据.txt. 在


Tags: 文件数据samplehttpstxtcomjson终端
2条回答

我不知道语言是否能保证这一点,但我知道它至少能在Unix上与cpython2.x和3.3+一起工作。所以如果你不关心3.0-3.2(或者可以自己测试),也不关心Windows(或者可以自己测试)

当到达EOF时,for line in f循环将结束。但它不会关闭文件或任何东西;它所做的只是将文件指针留在EOF。如果您再次尝试循环,并且写入了更多数据,您将获得新数据。在

所以,你可以这样做:

with open("/Users/me/raw-data.txt") as f:
    while True:
        for line in f:
            try:
                posts.append(json.loads(line))
            except:
                pass

问题是当你到达EOF时,它会以尽可能快的速度旋转,从而验证它是否仍在EOF。所以你真正想做的是阻止,直到有更多的数据。在某些Unix平台上,您可以使用select来实现这一点,但不是所有平台。您可以使用特定于平台的文件通知API,或围绕这些API的跨平台包装器。在

如果您使用的是python3.4+,那么可以在stdlib中使用^{}模块,这将为您提供在Solaris、Linux、OS X和其他任何带有kqueue的*BSD上工作的功能,并且在某些Unix平台上只使用select的一些Unix平台上,它将失败,并且在某些Unix系统上,它将尽可能快地旋转。如果找不到一个好的选择器,你可以通过拒绝启动来解决这个问题。在

或者,如果最坏的情况发生了,你可以在EOF时睡一会儿(可能会有一些指数级的回退,但只能达到一个相当短的限度)。这就是tail -f在无法检测通知的平台的端口中所做的事情。在

所以:

^{pr2}$

我想这是一个XY problem。因为您想不出在Python中逐行流式传输HTTP请求的方法,所以您决定使用curl对文件进行流式下载,然后从Python中读取该文件。因为您这样做了,您必须处理在请求仍在进行时遇到EOF的可能性,因为您已经赶上了curl。所以你无缘无故地让自己难受。在

虽然流式下载可以用stdlib完成,但这有点痛苦,^{}库使它更容易。所以,让我们用这个方法:

import json
import requests
from requests.auth import HTTPBasicAuth

posts = []
url = 'https://stream.twitter.com/1.1/statuses/sample.json'
r = requests.get(url, auth=('dhelm', '12345'), stream=True)
for line in r.iter_lines():
    try:
        posts.append(json.loads(line))
    except:
        pass

这就是整个计划。在

相关问题 更多 >