zeromq:TypeError:字符串索引必须是整数,而不是str

时间:2014-10-13 03:30:55

标签: python ipc zeromq

我想在机器之间建立发布订阅通信。

我拥有的两台计算机是ryu-primaryryu-secondary

我在每台机器中遵循的步骤如下:

ryu-primary的初始值设定项中(IP地址为192.168.241.131)

 self.context    = zmq.Context()
 self.sub_socket = self.context.socket(zmq.SUB)
 self.pub_socket = self.context.socket(zmq.PUB)
 self.pub_port   = 5566
 self.sub_port   = 5566


def establish_zmq_connection(self):                      # Socket to talk to server
    print( "Connection to ryu-secondary..." )
    self.sub_socket.connect( "tcp://192.168.241.132:%s" % self.sub_port )

def listen_zmq_connection(self):
    print( 'Listen to zmq connection' )
    self.pub_socket.bind( "tcp://*:%s" % self.pub_port )

def recieve_messages(self):
    while True:
        try:
            string = self.sub_socket.recv( flags=zmq.NOBLOCK )
            print( 'flow mod messages recieved {}'.format(string) )
            return string
        except zmq.ZMQError:
            break

def push_messages(self,msg):
    self.pub_socket.send( "%s" % (msg) )

来自ryu-secondary(IP地址 - 192.168.241.132)

在初始化程序中

    self.context    = zmq.Context()
    self.sub_socket = self.context.socket(zmq.SUB)
    self.pub_socket = self.context.socket(zmq.PUB)
    self.pub_port   = 5566
    self.sub_port   = 5566


def establish_zmq_connection(self):                     # Socket to talk to server
     print( "Connection to ryu-secondary..." )
     self.sub_socket.connect( "tcp://192.168.241.131:%s" % self.sub_port )

def listen_zmq_connection(self):
     print( 'Listen to zmq connection' )
     self.pub_socket.bind( "tcp://*:%s" % self.pub_port )

def recieve_messages(self):
    while True:
        try:
            string = self.sub_socket.recv( flags=zmq.NOBLOCK )
            print( 'flow mod messages recieved {}'.format(string) )
            return string
        except zmq.ZMQError:
            break

def push_messages(self,msg):
    print( 'pushing message to publish socket' )
    self.pub_socket.send( "%s" % (msg) )

这些是我的功能。

我正在呼叫ryu-secondary

establish_zmq_connections()
push_messages() 

ryu-primary时,我打电话

listen_zmq_connection()
recieve_messages() 
使用 .setsockopt( zmq.SUBSCRIBE = '') 订阅所有类型的邮件之后

但是我尝试发送的消息属于以下类型。

msg = {'in_port':in_port,'dst':dst,'actions':actions}
self.push_messages(msg)

然而另一方面(recieve_messages()我在执行此操作时出现以下错误

flow_mod = recieve_messages() 

flow_mod['in_port']
flow_mod['dst']
flow_mod['actions']


TypeError: string indices must be integers, not str

2 个答案:

答案 0 :(得分:1)

msg是一个Python dict,但是你发送(和接收)格式化为字符串的消息。可能最简单的方法是将msg序列化为JSON格式,将其作为字符串发送,然后再将接收到的字符串重新加载到dict中。然后,只有这样,您才能正确访问键和值。这样的事情应该有用(确保你import json在上面某处):

# on the sending end
msg = {'in_port':in_port,'dst':dst,'actions':actions}
msg_string = json.dumps(msg)
self.push_messages(msg)

# on the receiving end
payload = receive_messages()
message = json.loads(payload)

您可以找到json模块here(适用于Python 2)和{3}}适用于Python 3的完整文档。

答案 1 :(得分:0)

ZeroMQ API背景

ZeroMQ .send() .recv() 方法对字符串进行操作。您向他们传递了一个他们不知道如何处理的字典对象。将字典对象转换为JSON格式,作为针对这种情况的序列化示例,您的工作已经完成。

答案=获取TypeError的原因是什么?

正如写的那样,ZeroMQ的.send()方法在发送它不理解的对象方面做得不多,而.recv()部分仍然可以读取ZeroMQ层上传递的任何内容。

因此,您的 flow_mod 变量正确地在函数字符串作为 return string 指令> recieve_messages() 订单。

string = self.sub_socket.recv( flags=zmq.NOBLOCK ) 只是提供任何字符串,无论是空字符串还是从套接字的另一端收到的任何非零长度字符串。

<强>最后: flow_mod['in_port'] 会语法崩溃(并且必须这样做),因为变量flow_mod的内容已分配给&amp;在此之前进行类型调整,没有类似于字典的访问方法来处理这种类型的语法。

因此,必须在此处提出 TypeError: string indices must be integers, not str 例外。

<强> Q.E.D。


JSON序列化对象表示 - 编码&amp;解码简介:

>>> import json
>>> print json.__doc__
JSON (JavaScript Object Notation) <http://json.org> is a subset of
JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
interchange format.

[json] exposes an API familiar to users of the standard library
[marshal] and [pickle] modules. It is the externally maintained
version of the [json] library contained in Python 2.6, but maintains
compatibility with Python 2.4 and Python 2.5 and (currently) has
significant performance advantages, even without using the optional C
extension for speedups.

Encoding basic Python object hierarchies::

    >>> import json
    >>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
    '["foo", {"bar": ["baz", null, 1.0, 2]}]'
    >>> print json.dumps("\"foo\bar")
    "\"foo\bar"
    >>> print json.dumps(u'\u1234')
    "\u1234"
    >>> print json.dumps('\\')
    "\\"
    >>> print json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True)
    {"a": 0, "b": 0, "c": 0}
    >>> from StringIO import StringIO
    >>> io = StringIO()
    >>> json.dump(['streaming API'], io)
    >>> io.getvalue()
    '["streaming API"]'

Compact encoding::

    >>> import json
    >>> json.dumps([1,2,3,{'4': 5, '6': 7}], sort_keys=True, separators=(',',':'))
    '[1,2,3,{"4":5,"6":7}]'

Pretty printing::

    >>> import json
    >>> print json.dumps({'4': 5, '6': 7}, sort_keys=True,
    ...                  indent=4, separators=(',', ': '))
    {
        "4": 5,
        "6": 7
    }

Decoding JSON::

    >>> import json
    >>> obj = [u'foo', {u'bar': [u'baz', None, 1.0, 2]}]
    >>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]') == obj
    True
    >>> json.loads('"\\"foo\\bar"') == u'"foo\x08ar'
    True
    >>> from StringIO import StringIO
    >>> io = StringIO('["streaming API"]')
    >>> json.load(io)[0] == 'streaming API'
    True

Specializing JSON object decoding::

    >>> import json
    >>> def as_complex(dct):
    ...     if '__complex__' in dct:
    ...         return complex(dct['real'], dct['imag'])
    ...     return dct
    ...
    >>> json.loads('{"__complex__": true, "real": 1, "imag": 2}',
    ...     object_hook=as_complex)
    (1+2j)
    >>> from decimal import Decimal
    >>> json.loads('1.1', parse_float=Decimal) == Decimal('1.1')
    True

Specializing JSON object encoding::

    >>> import json
    >>> def encode_complex(obj):
    ...     if isinstance(obj, complex):
    ...         return [obj.real, obj.imag]
    ...     raise TypeError(repr(o) + " is not JSON serializable")
    ...
    >>> json.dumps(2 + 1j, default=encode_complex)
    '[2.0, 1.0]'
    >>> json.JSONEncoder(default=encode_complex).encode(2 + 1j)
    '[2.0, 1.0]'
    >>> ''.join(json.JSONEncoder(default=encode_complex).iterencode(2 + 1j))
    '[2.0, 1.0]'