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

时间:2014-08-23 00:04:37

标签: python json file curl

在我的终端中,我正在运行:

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

curl的输出是直播的Twitter数据,正在写入文件raw-data.txt

在python中,

 import json
 posts = []

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

我在python中读取文件并使用json解码器并将结果附加到帖子。

现在,问题是我不希望我的程序在python脚本到达文件末尾时结束。相反,当我在终端上运行的卷曲将更多帖子附加到文件raw-data.txt时,我想继续阅读。

2 个答案:

答案 0 :(得分:1)

我不知道语言是否可以保证这一点,但我知道它在Unix上至少至少 CPython 2.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的跨平台包装器。

如果您使用的是Python 3.4+,则可以使用stdlib中的selectors模块,它将为您提供适用于Solaris,Linux,OS X和任何其他* BSD {{3}的模块。 1}},并且在一些只有kqueue的Unix平台上......但是在Windows上它会失败,而在某些Unix系统上它会尽可能快地旋转。如果你找不到好的选择器,你可以通过拒绝开始来解决这个问题。

或者,如果最坏的情况发生,你可以在EOF睡觉一下(可能有一些指数退避,但只能达到合理的短暂限制)。这是select在无法检测通知的平台的端口中所做的事情。

所以:

tail -f

答案 1 :(得分:1)

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

虽然流式下载可以使用stdlib完成,但它有点痛苦; requests库让它变得更容易。所以,让我们使用:

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

这就是整个计划。