python-trio: AttributeError: sendall
python-trio: AttributeError: sendall
我只是想 运行 echo-client-low-level.py
来自 python-trio
docs:
# 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'
糟糕,这是文档中的一个错误 – 感谢您的发现。 sockets 上曾经有一个 sendall
方法,但是 it had problems 并且是介于低层和高层之间的一个奇怪的特性,所以它在 0.3.0 中被删除了。但是我错过了在那里更新文档。
我真的需要重写该部分以使用新的高级 APIs! (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)
它们与文本不太匹配,抱歉!但希望他们能给你一些机会弄清楚发生了什么,直到我真正修复文档。
我只是想 运行 echo-client-low-level.py
来自 python-trio
docs:
# 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'
糟糕,这是文档中的一个错误 – 感谢您的发现。 sockets 上曾经有一个 sendall
方法,但是 it had problems 并且是介于低层和高层之间的一个奇怪的特性,所以它在 0.3.0 中被删除了。但是我错过了在那里更新文档。
我真的需要重写该部分以使用新的高级 APIs! (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)
它们与文本不太匹配,抱歉!但希望他们能给你一些机会弄清楚发生了什么,直到我真正修复文档。