【问题标题】:python-trio: AttributeError: sendallpython-trio: AttributeError: sendall
【发布时间】:2018-07-24 11:13:41
【问题描述】:

我只是想从python-trio docs 运行echo-client-low-level.py

# echo-client-low-level.py

import sys
import trio

# arbitrary, but:
# - must be in between 1024 and 65535
# - can't be in use by some other program on your computer
# - must match what we set in our echo server
PORT = 12345
# How much memory to spend (at most) on each call to recv. Pretty arbitrary,
# but shouldn't be too big or too small.
BUFSIZE = 16384

async def sender(client_sock):
    print("sender: started!")
    while True:
        data = b"async can sometimes be confusing, but I believe in you!"
        print("sender: sending {!r}".format(data))
        await client_sock.sendall(data)
        await trio.sleep(1)

async def receiver(client_sock):
    print("receiver: started!")
    while True:
        data = await client_sock.recv(BUFSIZE)
        print("receiver: got data {!r}".format(data))
        if not data:
            print("receiver: connection closed")
            sys.exit()

async def parent():
    print("parent: connecting to 127.0.0.1:{}".format(PORT))
    with trio.socket.socket() as client_sock:
        await client_sock.connect(("127.0.0.1", PORT))
        async with trio.open_nursery() as nursery:
            print("parent: spawning sender...")
            nursery.start_soon(sender, client_sock)

            print("parent: spawning receiver...")
            nursery.start_soon(receiver, client_sock)

trio.run(parent)

但是他们的示例产生了一个讨厌的AttributeError: sendall 错误:

$ python echo-client-low-level.py 
parent: connecting to 127.0.0.1:12345
parent: spawning sender...
parent: spawning receiver...
sender: started!
sender: sending b'async can sometimes be confusing, but I believe in you!'
receiver: started!
Traceback (most recent call last):
  File "echo-client-low-level.py", line 43, in <module>
    trio.run(parent)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 1225, in run
    return result.unwrap()
  File "/usr/lib/python3.6/site-packages/trio/_core/_result.py", line 119, in unwrap
    raise self.error
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 1334, in run_impl
    msg = task.coro.send(next_send)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 923, in init
    self.entry_queue.spawn()
  File "/usr/lib/python3.6/site-packages/trio/_util.py", line 109, in __aexit__
    await self._agen.asend(None)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 274, in asend
    return await self._do_it(self._it.send, value)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 290, in _do_it
    return await ANextIter(self._it, start_fn, *args)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 202, in send
    return self._invoke(self._it.send, value)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 209, in _invoke
    result = fn(*args)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 318, in open_nursery
    await nursery._nested_child_finished(nested_child_exc)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 203, in open_cancel_scope
    yield scope
  File "/usr/lib/python3.6/site-packages/trio/_core/_multierror.py", line 144, in __exit__
    raise filtered_exc
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 203, in open_cancel_scope
    yield scope
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 318, in open_nursery
    await nursery._nested_child_finished(nested_child_exc)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 427, in _nested_child_finished
    raise MultiError(self._pending_excs)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 1334, in run_impl
    msg = task.coro.send(next_send)
  File "echo-client-low-level.py", line 41, in parent
    nursery.start_soon(receiver, client_sock)
  File "/usr/lib/python3.6/site-packages/trio/_util.py", line 109, in __aexit__
    await self._agen.asend(None)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 274, in asend
    return await self._do_it(self._it.send, value)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 290, in _do_it
    return await ANextIter(self._it, start_fn, *args)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 202, in send
    return self._invoke(self._it.send, value)
  File "/usr/lib/python3.6/site-packages/async_generator/_impl.py", line 209, in _invoke
    result = fn(*args)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 318, in open_nursery
    await nursery._nested_child_finished(nested_child_exc)
  File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 203, in open_cancel_scope
    yield scope
  File "/usr/lib/python3.6/site-packages/trio/_core/_multierror.py", line 144, in __exit__
    raise filtered_exc
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 203, in open_cancel_scope
    yield scope
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 318, in open_nursery
    await nursery._nested_child_finished(nested_child_exc)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 427, in _nested_child_finished
    raise MultiError(self._pending_excs)
  File "/usr/lib/python3.6/site-packages/trio/_core/_run.py", line 1334, in run_impl
    msg = task.coro.send(next_send)
  File "echo-client-low-level.py", line 20, in sender
    await client_sock.sendall(data)
  File "/usr/lib/python3.6/site-packages/trio/_socket.py", line 426, in __getattr__
    raise AttributeError(name)
AttributeError: sendall

检查GitHub 后,似乎sendall 一直是intentionally omitted

我有点困惑,我错过了什么吗?

In [3]: trio.__version__
Out[3]: '0.3.0'

【问题讨论】:

    标签: python-3.5 python-3.6 python-trio


    【解决方案1】:

    哎呀,这是文档中的一个错误 - 感谢您的发现。以前在套接字上有一个sendall 方法,但是it had problems 是一个介于低层和高层之间的奇怪特性,因此在 0.3.0 中被删除。但我错过了更新那里的文档。

    我真的需要重写该部分以使用新的高级 API! (Bug filed.) 但是现在这里将示例快速翻译成新的(更好的、更高级别的)API:

    客户:

    # echo-client.py
    
    import sys
    import trio
    
    # arbitrary, but:
    # - must be in between 1024 and 65535
    # - can't be in use by some other program on your computer
    # - must match what we set in our echo server
    PORT = 12345
    # How much memory to spend (at most) on each call to recv. Pretty arbitrary,
    # but shouldn't be too big or too small.
    BUFSIZE = 16384
    
    async def sender(client_stream):
        print("sender: started!")
        while True:
            data = b"async can sometimes be confusing, but I believe in you!"
            print("sender: sending {!r}".format(data))
            await client_stream.send_all(data)
            await trio.sleep(1)
    
    async def receiver(client_stream):
        print("receiver: started!")
        while True:
            data = await client_stream.receive_some(BUFSIZE)
            print("receiver: got data {!r}".format(data))
            if not data:
                print("receiver: connection closed")
                sys.exit()
    
    async def parent():
        print("parent: connecting to 127.0.0.1:{}".format(PORT))
        client_stream = await trio.open_tcp_stream("127.0.0.1", PORT)
        async with client_stream:
            async with trio.open_nursery() as nursery:
                print("parent: spawning sender...")
                nursery.start_soon(sender, client_stream)
    
                print("parent: spawning receiver...")
                nursery.start_soon(receiver, client_stream)
    
    trio.run(parent)
    

    服务器

    # echo-server.py
    
    import trio
    from itertools import count
    
    # Port is arbitrary, but:
    # - must be in between 1024 and 65535
    # - can't be in use by some other program on your computer
    # - must match what we set in our echo client
    PORT = 12345
    # How much memory to spend (at most) on each call to recv. Pretty arbitrary,
    # but shouldn't be too big or too small.
    BUFSIZE = 16384
    
    CONNECTION_COUNTER = count()
    
    async def echo_server(server_stream):
        # Assign each connection a unique number to make our logging easier to
        # understand
        ident = next(CONNECTION_COUNTER)
        print("echo_server {}: started".format(ident))
        try:
            while True:
                data = await server_stream.receive_some(BUFSIZE)
                print("echo_server {}: received data {!r}".format(ident, data))
                if not data:
                    print("echo_server {}: connection closed".format(ident))
                    return
                print("echo_server {}: sending data {!r}".format(ident, data))
                await server_stream.send_all(data)
        except Exception as exc:
            # Unhandled exceptions will propagate into our parent and take
            # down the whole program. If the exception is KeyboardInterrupt,
            # that's what we want, but otherwise maybe not...
            print("echo_server {}: crashed: {!r}".format(ident, exc))
    
    async def main():
        await trio.serve_tcp(echo_server, PORT)
    
    # We could also just write 'trio.run(serve_tcp, echo_server, PORT)', but real
    # programs almost always end up doing other stuff too and then we'd have to go
    # back and factor it out into a separate function anyway. So it's simplest to
    # just make it a standalone function from the beginning.
    trio.run(main)
    

    它们与文本不完全匹配,抱歉!但希望他们能给你一些机会弄清楚发生了什么,直到我能真正修复文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 2023-01-22
      • 1970-01-01
      • 2018-07-14
      • 1970-01-01
      • 2021-10-11
      相关资源
      最近更新 更多