如何检查 Windows 和 Python 3.7+ 中的 asyncio StreamReader 是否要读取某些内容?
How can I check if something to read in asyncio StreamReader in Windows and Python 3.7+?
我尝试与 Stockfish 通信(它是 stdin/stdout 应用程序)。
它是这样工作的:
- 我将一些行发送到标准输入。
- 它立即将一些行响应到标准输出。
- 它可以连续响应下一行(新动作评估)。
- Stockfish 永远不会停止,所以
communicate()
不会工作,因为它不是设计者。 add_reader
不适用于 Windows。
正在连续发送不可预测的行数。
问题是当我调用 await stdout.readline()
时它是否阻塞了程序流我不想要阻塞流但检查是否读取了新行。我怎样才能不阻塞地读取行。
我做的一些代码——没什么复杂的:
import asyncio
import sys
def stockfish_read_stdout(line):
print(line)
async def run_stockfish():
STOCKFISH_PATH = r'C:\root\chess\stockfish\stockfish 9\stockfish_9_x64_bmi2.exe'
stockfish = await asyncio.subprocess.create_subprocess_exec(
STOCKFISH_PATH,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
# It is maybe not work since output is not complete.
stockfish.stdin.write('uci'.encode())
# How to check if line read to read?
# I put True but here should be check.
while True:
line = await stockfish.stdout.readline()
print(line)
await stockfish.wait()
if sys.platform == "win32":
asyncio.set_event_loop_policy(
asyncio.WindowsProactorEventLoopPolicy())
asyncio.run(run_stockfish(), debug=True)
输出为:
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)] on win32
runfile('C:/Users/Cezary Wagner/PycharmProjects/stockfish-proxy/sandbox/async_proxy/s01_async_stockfish.py', wdir='C:/Users/Cezary Wagner/PycharmProjects/stockfish-proxy/sandbox/async_proxy')
b'Stockfish 9 64 BMI2 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott\r\n'
但应该在uci
之后:
Stockfish 9 64 BMI2 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott
uci
id name Stockfish 9 64 BMI2
id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott
option name Debug Log File type string default
option name Contempt type spin default 20 min -100 max 100
option name Threads type spin default 1 min 1 max 512
option name Hash type spin default 16 min 1 max 131072
option name Clear Hash type button
option name Ponder type check default false
option name MultiPV type spin default 1 min 1 max 500
option name Skill Level type spin default 20 min 0 max 20
option name Move Overhead type spin default 30 min 0 max 5000
option name Minimum Thinking Time type spin default 20 min 0 max 5000
option name Slow Mover type spin default 89 min 10 max 1000
option name nodestime type spin default 0 min 0 max 10000
option name UCI_Chess960 type check default false
option name SyzygyPath type string default
option name SyzygyProbeDepth type spin default 1 min 1 max 100
option name Syzygy50MoveRule type check default true
option name SyzygyProbeLimit type spin default 6 min 0 max 6
uciok
您需要创建一个单独的协程,它将从进程的标准输出缓冲区读取行,因为 await
阻止 当前 协程执行,直到收到结果。
async def reader(process, msg_handler, exit_handler):
while not process.stdout.at_eof():
line = await process.stdout.readline()
msg_handler(line.decode())
# Finished
exit_handler()
现在您可以运行它作为事件循环中的任务。
async def run_stockfish():
STOCKFISH_PATH = r'C:\root\chess\stockfish\stockfish 9\stockfish_9_x64_bmi2.exe'
stockfish = await asyncio.subprocess.create_subprocess_exec(
STOCKFISH_PATH,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
# It is maybe not work since output is not complete.
stockfish.stdin.write('uci\n'.encode())
task = asyncio.create_task(reader(stockfish,
lambda msg: print(f'Output: {msg}'),
lambda: print('EOF'))
# asyncio.create_task won't block this coroutine
希望还不算太晚。
我尝试与 Stockfish 通信(它是 stdin/stdout 应用程序)。
它是这样工作的:
- 我将一些行发送到标准输入。
- 它立即将一些行响应到标准输出。
- 它可以连续响应下一行(新动作评估)。
- Stockfish 永远不会停止,所以
communicate()
不会工作,因为它不是设计者。add_reader
不适用于 Windows。
正在连续发送不可预测的行数。
问题是当我调用 await stdout.readline()
时它是否阻塞了程序流我不想要阻塞流但检查是否读取了新行。我怎样才能不阻塞地读取行。
我做的一些代码——没什么复杂的:
import asyncio
import sys
def stockfish_read_stdout(line):
print(line)
async def run_stockfish():
STOCKFISH_PATH = r'C:\root\chess\stockfish\stockfish 9\stockfish_9_x64_bmi2.exe'
stockfish = await asyncio.subprocess.create_subprocess_exec(
STOCKFISH_PATH,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
# It is maybe not work since output is not complete.
stockfish.stdin.write('uci'.encode())
# How to check if line read to read?
# I put True but here should be check.
while True:
line = await stockfish.stdout.readline()
print(line)
await stockfish.wait()
if sys.platform == "win32":
asyncio.set_event_loop_policy(
asyncio.WindowsProactorEventLoopPolicy())
asyncio.run(run_stockfish(), debug=True)
输出为:
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 14:57:15) [MSC v.1915 64 bit (AMD64)] on win32 runfile('C:/Users/Cezary Wagner/PycharmProjects/stockfish-proxy/sandbox/async_proxy/s01_async_stockfish.py', wdir='C:/Users/Cezary Wagner/PycharmProjects/stockfish-proxy/sandbox/async_proxy') b'Stockfish 9 64 BMI2 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott\r\n'
但应该在uci
之后:
Stockfish 9 64 BMI2 by T. Romstad, M. Costalba, J. Kiiski, G. Linscott uci id name Stockfish 9 64 BMI2 id author T. Romstad, M. Costalba, J. Kiiski, G. Linscott option name Debug Log File type string default option name Contempt type spin default 20 min -100 max 100 option name Threads type spin default 1 min 1 max 512 option name Hash type spin default 16 min 1 max 131072 option name Clear Hash type button option name Ponder type check default false option name MultiPV type spin default 1 min 1 max 500 option name Skill Level type spin default 20 min 0 max 20 option name Move Overhead type spin default 30 min 0 max 5000 option name Minimum Thinking Time type spin default 20 min 0 max 5000 option name Slow Mover type spin default 89 min 10 max 1000 option name nodestime type spin default 0 min 0 max 10000 option name UCI_Chess960 type check default false option name SyzygyPath type string default option name SyzygyProbeDepth type spin default 1 min 1 max 100 option name Syzygy50MoveRule type check default true option name SyzygyProbeLimit type spin default 6 min 0 max 6 uciok
您需要创建一个单独的协程,它将从进程的标准输出缓冲区读取行,因为 await
阻止 当前 协程执行,直到收到结果。
async def reader(process, msg_handler, exit_handler):
while not process.stdout.at_eof():
line = await process.stdout.readline()
msg_handler(line.decode())
# Finished
exit_handler()
现在您可以运行它作为事件循环中的任务。
async def run_stockfish():
STOCKFISH_PATH = r'C:\root\chess\stockfish\stockfish 9\stockfish_9_x64_bmi2.exe'
stockfish = await asyncio.subprocess.create_subprocess_exec(
STOCKFISH_PATH,
stdin=asyncio.subprocess.PIPE,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
# It is maybe not work since output is not complete.
stockfish.stdin.write('uci\n'.encode())
task = asyncio.create_task(reader(stockfish,
lambda msg: print(f'Output: {msg}'),
lambda: print('EOF'))
# asyncio.create_task won't block this coroutine
希望还不算太晚。