将io搬到单独的io线程

This commit is contained in:
limil 2024-10-28 09:26:48 +08:00
parent 55533abdd6
commit d012ba0e34
2 changed files with 42 additions and 13 deletions

53
main.py
View File

@ -1,8 +1,8 @@
import asyncio, nest_asyncio import asyncio, nest_asyncio
import cmd2 import cmd2
from functools import wraps from functools import wraps
from aioconsole import ainput, aprint
import logging import logging
import threading
import colorlog import colorlog
from pikpakFs import VirtFsNode, DirNode, FileNode, PKVirtFs from pikpakFs import VirtFsNode, DirNode, FileNode, PKVirtFs
import os import os
@ -66,13 +66,40 @@ class PikpakConsole(cmd2.Cmd):
self._SetupLogging() self._SetupLogging()
self.client = PKVirtFs("token.json", proxy="http://127.0.0.1:7897") self.client = PKVirtFs("token.json", proxy="http://127.0.0.1:7897")
def IOWorker(self, loop):
self.terminal_lock.acquire() # 我看cmdloop是这么做的所以我也这么做
asyncio.set_event_loop(loop)
try:
loop.run_forever()
finally:
self.terminal_lock.release()
async def ainput(self, prompt):
async def ReadInput(prompt):
return self._read_command_line(prompt)
future = asyncio.run_coroutine_threadsafe(ReadInput(prompt), self.ioLoop)
return await asyncio.wrap_future(future)
async def aoutput(self, output):
async def PrintOuput(output):
print(output)
future = asyncio.run_coroutine_threadsafe(PrintOuput(output), self.ioLoop)
await asyncio.wrap_future(future)
async def Run(self): async def Run(self):
# 1. 设置忽略SIGINT
import signal import signal
def signal_handler(sig, frame): def signal_handler(sig, frame):
pass pass
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGINT, signal_handler)
self.loop = asyncio.get_running_loop()
# 2. 创建一个新的事件循环
self.loop = asyncio.get_running_loop()
self.ioLoop = asyncio.new_event_loop()
thread = threading.Thread(target=self.IOWorker, args=(self.ioLoop,))
thread.start()
# 3. 启动cmd2
saved_readline_settings = None saved_readline_settings = None
try: try:
# Get sigint protection while we set up readline for cmd2 # Get sigint protection while we set up readline for cmd2
@ -82,7 +109,7 @@ class PikpakConsole(cmd2.Cmd):
stop = False stop = False
while not stop: while not stop:
# Get sigint protection while we read the command line # Get sigint protection while we read the command line
line = await asyncio.to_thread(self._read_command_line, self.prompt) line = await self.ainput(self.prompt)
# Run the command along with all associated pre and post hooks # Run the command along with all associated pre and post hooks
stop = self.onecmd_plus_hooks(line) stop = self.onecmd_plus_hooks(line)
finally: finally:
@ -90,6 +117,8 @@ class PikpakConsole(cmd2.Cmd):
with self.sigint_protection: with self.sigint_protection:
if saved_readline_settings is not None: if saved_readline_settings is not None:
self._restore_readline(saved_readline_settings) self._restore_readline(saved_readline_settings)
self.ioLoop.stop()
thread.join()
def do_debug(self, args): def do_debug(self, args):
""" """
@ -116,7 +145,7 @@ class PikpakConsole(cmd2.Cmd):
Login to pikpak Login to pikpak
""" """
await self.client.Login(args.username, args.password) await self.client.Login(args.username, args.password)
await aprint("Logged in successfully") await self.aoutput("Logged in successfully")
def ParserProvider(self): def ParserProvider(self):
return cmd2.Cmd2ArgumentParser() return cmd2.Cmd2ArgumentParser()
@ -169,12 +198,12 @@ class PikpakConsole(cmd2.Cmd):
if isinstance(args.path, DirNode): if isinstance(args.path, DirNode):
for childId in args.path.childrenId: for childId in args.path.childrenId:
node = self.client.nodes[childId] node = self.client.nodes[childId]
await aprint(node.name) await self.aoutput(node.name)
elif isinstance(args.path, FileNode): elif isinstance(args.path, FileNode):
await self.client.UpdateDownloadUrl(args.path) await self.client.UpdateDownloadUrl(args.path)
await aprint(f"{args.path.name}: {args.path.url}") await self.aoutput(f"{args.path.name}: {args.path.url}")
else: else:
await aprint("Invalid path") await self.aoutput("Invalid path")
@RunSync @RunSync
async def complete_cd(self, text, line, begidx, endidx): async def complete_cd(self, text, line, begidx, endidx):
@ -187,7 +216,7 @@ class PikpakConsole(cmd2.Cmd):
Change directory Change directory
""" """
if self.client.ToDir(args.path) is None: if self.client.ToDir(args.path) is None:
await aprint("Invalid directory") await self.aoutput("Invalid directory")
return return
self.client.currentLocation = args.path self.client.currentLocation = args.path
@ -196,7 +225,7 @@ class PikpakConsole(cmd2.Cmd):
""" """
Print current working directory Print current working directory
""" """
await aprint(self.client.NodeToPath(self.client.currentLocation)) await self.aoutput(self.client.NodeToPath(self.client.currentLocation))
def do_clear(self, args): def do_clear(self, args):
""" """
@ -236,11 +265,11 @@ class PikpakConsole(cmd2.Cmd):
father, sonName = args.path father, sonName = args.path
fatherDir = self.client.ToDir(father) fatherDir = self.client.ToDir(father)
if fatherDir == None or sonName == "" or sonName == None: if fatherDir == None or sonName == "" or sonName == None:
await aprint("Invalid path") await self.aoutput("Invalid path")
return return
childNode = self.client.FindChildInDirByName(fatherDir, sonName) childNode = self.client.FindChildInDirByName(fatherDir, sonName)
if childNode is not None: if childNode is not None:
await aprint("Path already exists") await self.aoutput("Path already exists")
return return
for i in range(1, 10): for i in range(1, 10):
await self.client.MakeDir(fatherDir, sonName + str(i)) await self.client.MakeDir(fatherDir, sonName + str(i))
@ -259,7 +288,7 @@ class PikpakConsole(cmd2.Cmd):
Download a file Download a file
""" """
if self.client.ToDir(args.path) is None: if self.client.ToDir(args.path) is None:
await aprint("Invalid directory") await self.aoutput("Invalid directory")
return return
await self.client.Download(args.url, args.path) await self.client.Download(args.url, args.path)

View File

@ -147,7 +147,7 @@ class PKVirtFs:
next_page_token = None next_page_token = None
nodes = [] nodes = []
while True: while True:
dirInfo = await self.client.file_list(parent_id = dirNode.id, next_page_token=next_page_token, size=3) dirInfo = await self.client.file_list(parent_id = dirNode.id, next_page_token=next_page_token)
next_page_token = dirInfo["next_page_token"] next_page_token = dirInfo["next_page_token"]
currentPageNodes = dirInfo["files"] currentPageNodes = dirInfo["files"]
nodes.extend(currentPageNodes) nodes.extend(currentPageNodes)