/
main.py
executable file
·156 lines (118 loc) · 4.06 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# filename: main.py
# modified: 2019-09-11
import os
import time
from optparse import OptionParser
from multiprocessing import Process, Manager, Queue
from autoelective import __version__, __date__
from autoelective.config import AutoElectiveConfig
from autoelective.parser import load_course_csv
from autoelective.logger import ConsoleLogger
from autoelective.loop import main as run_main_loop
from autoelective.monitor import main as run_monitor
from autoelective.const import SIGNAL_KILL_ALL_PROCESSES
from autoelective._internal import userInfo as _userInfo # ugly !
def task_run_loop(userInfo):
config = AutoElectiveConfig() # create singleton first
cout = ConsoleLogger("main")
signals = Queue()
p = Process(target=run_main_loop, name="Main", args=(signals, userInfo))
p.daemon = True
p.start()
while True:
try:
signal = signals.get() # block process
except KeyboardInterrupt as e:
cout.info("Process %s is killed" % os.getpid())
return
time.sleep(0.1) # wait a minute
if signal == SIGNAL_KILL_ALL_PROCESSES:
if p.is_alive():
p.terminate()
cout.info("Process %s is killed" % p.name)
break
def task_run_loop_with_monitor(userInfo):
config = AutoElectiveConfig() # create singleton first
cout = ConsoleLogger("main")
signals = Queue()
with Manager() as manager:
# shared objects
goals = manager.list(load_course_csv())
ignored = manager.list()
status = manager.dict()
status["main_loop"] = 0
status["login_loop"] = 0
status["error_count"] = 0
status["errors"] = manager.dict()
args = (signals, userInfo, goals, ignored, status)
pList = [
Process(target=run_main_loop, name="Main", args=args),
Process(target=run_monitor, name="Monitor", args=args),
]
for p in pList:
p.daemon = True
p.start()
while True:
try:
signal = signals.get() # block process
except KeyboardInterrupt as e:
cout.info("Process %s is killed" % os.getpid())
return
time.sleep(0.1) # wait a minute
if signal == SIGNAL_KILL_ALL_PROCESSES:
for p in pList:
if p.is_alive():
p.terminate()
cout.info("Process %s is killed" % p.name)
break
def main():
parser = OptionParser(
description='PKU Auto-Elective Tool v%s (%s)' % (__version__, __date__),
version=__version__,
)
# MARK: custom input files
parser.add_option(
'--config',
dest='CONFIG_INI',
metavar="FILE",
help='custom config file encoded with utf8',
)
parser.add_option(
'--course-csv-utf8',
dest='COURSE_UTF8_CSV',
metavar="FILE",
help='custom course.csv file encoded with utf8',
)
parser.add_option(
'--course-csv-gbk',
dest='COURSE_GBK_CSV',
metavar="FILE",
help='custom course.csv file encoded with gbk',
)
# MARK: boolean (flag) options
parser.add_option(
'--with-monitor',
dest='with_monitor',
action='store_true',
default=False,
help='run the monitor process simultaneously',
)
options, args = parser.parse_args()
run_task = task_run_loop
# MARK: setup userInfo
userInfo = {}
if options.CONFIG_INI is not None:
userInfo["CONFIG_INI"] = options.CONFIG_INI
if options.COURSE_UTF8_CSV is not None:
userInfo["COURSE_UTF8_CSV"] = options.COURSE_UTF8_CSV
if options.COURSE_GBK_CSV is not None:
userInfo["COURSE_GBK_CSV"] = options.COURSE_GBK_CSV
# MAKR: handle boolean (flag) options
if options.with_monitor:
run_task = task_run_loop_with_monitor
_userInfo.update(userInfo) # setup userInfo first
run_task(userInfo)
if __name__ == '__main__':
main()