我正在用Python3.5编写Python脚本,我有一个主机和端口,我要做的是创建脚本,以便它能够不断地监视提供的主机的数据。数据以xml格式通过TCP流提要分发,标记标记为事件的开始和结束。
因此,我所要做的基本上是监视TCP提要中的新事件,这些事件在xml开始标记和结束标记之间标记,然后检索事件并在脚本中相应地处理它。此外,理想情况下,我需要在毫秒内访问提要中的新数据。
这个提要是一个分发警报的政府提要,这个提要正在流1.naad-adna.pelmore x.com,端口是8080,我想做的是监视这个提要以获取新的警报,然后能够访问警报并在Python中相应地处理它们。提要每分钟发送一次心跳,以指示连接是活动的。
我认为最好的选择是使用Socket,尽管我不知道如何在这个特定的用例中实现它们。我对TCP提要没有多少经验,在我的具体用例下,我无法在网上找到关于如何处理Python中的TCP提要的在线信息,我能够处理xml,但一旦我能够找到如何从TCP提要中提取它的方法。
任何帮助都将不胜感激。
发布于 2016-12-16 03:07:14
在你的问题中有几个技术上的挑战。
首先,连接到服务器并检索数据是一个简单的问题。正如您在下面的connect()中所看到的,这非常简单,只需创建一个套接字(s = socket.socket())并连接它(s.connect(('hostname', port_number)))。
下一个问题是以有用的形式检索数据。套接字本机提供.recv(),但我想要一个类似文件的接口。套接字模块提供了Python特有的方法:.makefile()。(return s.makefile('rb'))
现在我们到了最困难的部分。XML文档通常每个文件存储一个文档,或者每个TCP传输存储一个文档。因此,文档的结尾很容易被文件指示的结束或者Content-Length:头发现。因此,Python中没有一个在一个文件或一个字符串中处理多个XML文档的机制。我写xml_partition()是为了解决这个问题。xml_partition()使用类似文件的对象的数据,并从流中生成每个XML文档。(注意:必须将XML文档按在一起。在最终的>之后不允许使用空格)。
最后,有一个简短的测试程序(alerts()),它连接到流并读取几个XML文档,将每个文档存储到自己的文件中。
这里是一个从Pelmorex的国家警报聚合和传播系统下载紧急警报的程序。
import socket
import xml.etree.ElementTree as ET
def connect():
'Connect to pelmorex data stream and return a file-like object'
# Set up the socket
s = socket.socket()
s.connect(('streaming1.naad-adna.pelmorex.com', 8080))
return s.makefile('rb')
# We have to consume the XML data in bits and pieces
# so that we can stop precisely at the boundary between
# streamed XML documents. This function ensures that
# nothing follows a '>' in any XML fragment.
def partition(s, pattern):
'Consume a file-like object, and yield parts defined by pattern'
data = s.read(2048)
while data:
left, middle, data = data.partition(pattern)
while left or middle:
yield left
yield middle
left, middle, data = data.partition(pattern)
data = s.read(2048)
# Split the incoming XML stream into fragments (much smaller
# than an XML document.) The end of each XML document
# is guaranteed to align with the end of a fragment.
# Use an XML parser to determine the actual end of
# a document. Whenever the parser signals the end
# of an XML document, yield what we have so far and
# start a new parser.
def xml_partition(s):
'Read multiple XML documents from one data stream'
parser = None
for part in partition(s, b'>'):
if parser is None:
parser = ET.XMLPullParser(['start', 'end'])
starts = ends = 0
xml = []
xml.append(part)
parser.feed(part)
for event, elem in parser.read_events():
starts += event == "start"
ends += event == "end"
if starts == ends > 0:
# We have reached the end of the XML doc
parser.close()
parser = None
yield b''.join(xml)
# Typical usage:
def alerts():
for i, xml in enumerate(xml_partition(connect())):
# The XML is a bytes object that contains the undecoded
# XML stream. You'll probably want to parse it and
# somehow display the alert.
# I'm just saving it to a file.
with open('alert%d.xml' % i, 'wb') as fp:
fp.write(xml)
if i == 3:
break
def test():
# A test function that uses multiple XML documents in one
# file. This avoids the wait for a natural-disaster alert.
with open('multi.xml', 'rb') as fp:
print(list(xml_partition(fp)))
alerts()https://stackoverflow.com/questions/41132845
复制相似问题