build_all.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import os
  2. import re
  3. import sys
  4. from winpty import PtyProcess
  5. class BuildAll:
  6. def __init__(self):
  7. self.current_dir = os.path.dirname(os.path.abspath(__file__))
  8. @staticmethod
  9. def __get_python_env_name_from_args():
  10. for arg in sys.argv[1:]:
  11. if arg.startswith("-python_env_name="):
  12. return arg.split("=")[1]
  13. return None
  14. def build_all(self):
  15. python_env_name = self.__get_python_env_name_from_args()
  16. if not python_env_name:
  17. python_env_name = input("请输入conda python环境的名称(例如:base): ")
  18. # confirm_remove = input("是否删除输出目录及其所有内容? (y/N) ").strip().lower()
  19. confirm_remove = "y"
  20. pyinstaller_confirm_flag = "-y" if confirm_remove == 'y' else ""
  21. commands = [
  22. (f"conda activate {python_env_name} && Pyinstaller {pyinstaller_confirm_flag} -D launcher.py",
  23. self.current_dir),
  24. (f"conda activate {python_env_name} && Pyinstaller {pyinstaller_confirm_flag} -D server.py",
  25. os.path.join(self.current_dir, "server")),
  26. ("npm run build:win && echo BUILD_EXIT_WITH_NPM_RUN_END", os.path.join(self.current_dir, "client"))
  27. ]
  28. for cmd, cwd in commands:
  29. if not self.__pre_execute_check(cmd, cwd):
  30. return
  31. self.__execute_cmd_with_pty(cmd, cwd)
  32. print("Build complete!")
  33. @staticmethod
  34. def __pre_execute_check(cmd, cwd):
  35. if "Pyinstaller" in cmd:
  36. script_name = cmd.split(" ")[-1]
  37. absolute_path = os.path.join(cwd, script_name)
  38. if not os.path.exists(absolute_path):
  39. print(f"Error: Python脚本 '{absolute_path}' 不存在!")
  40. return False
  41. elif cmd.startswith("npm "):
  42. pass
  43. return True
  44. def __execute_cmd_with_pty(self, cmd, cwd=None):
  45. counter_output_is_all_none: int = 0
  46. process = PtyProcess.spawn(["cmd", "/c", cmd], cwd=cwd)
  47. process.setwinsize(20, 9999)
  48. while process.isalive():
  49. try:
  50. output: str = process.readline()
  51. output = self.__remove_ansi_escape_codes(output)
  52. output = self.__remove_leading_newlines(output)
  53. if output in ["", " ", "\n", "\r\n", "\n\r"]:
  54. if counter_output_is_all_none != 0:
  55. continue
  56. else:
  57. counter_output_is_all_none += 1
  58. print("\n", end='')
  59. continue
  60. else:
  61. counter_output_is_all_none = 0
  62. output = self.__remove_ending_newlines(output)
  63. print(output, end='\n')
  64. except EOFError:
  65. break # 当伪终端关闭时跳出循环
  66. @staticmethod
  67. def __remove_ansi_escape_codes(s):
  68. ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
  69. return ansi_escape.sub('', s)
  70. @staticmethod
  71. def __remove_leading_newlines(s):
  72. while s.startswith(('\n\r', '\r\n', '\n', '\r')):
  73. for seq in ['\n\r', '\r\n', '\n', '\r']:
  74. if s.startswith(seq):
  75. s = s[len(seq):]
  76. return s
  77. @staticmethod
  78. def __remove_ending_newlines(s):
  79. sequences = ['\n\r', '\r\n', '\n', '\r']
  80. while s.endswith(tuple(sequences)):
  81. for seq in sequences:
  82. if s.endswith(seq):
  83. s = s[:-len(seq)]
  84. return s
  85. if __name__ == "__main__":
  86. builder = BuildAll()
  87. builder.build_all()