我想创建一个永远运行的简单后台任务。我将找出与用Flask编写的Web应用程序同时启动它的方法。
到目前为止,我是这样的:
import threading
from app.models import SkillTracker, UserAttributes
from flask_sqlalchemy import SQLAlchemy
from app import db
import time, math
class SkillTimer(threading.Thread, SkillTracker):
def __init__(self, SkillTracker=SkillTracker):
threading.Thread.__init__(self)
self.skillcheck = SkillTracker.query.filter_by(isactive=1).all()
def run(self):
# for x in range(1, 1+1):
# if x%1 == 0:
# print(x)
# #print(x)
time.sleep(1)
self.skillcheck = SkillTracker.query.filter_by(isactive=1).all()
if self.skillcheck != []:
print(self.skillcheck)
for record in self.skillcheck:
if record.isactive == 1:
if record.timesubmit + record.timetowait <= time.time():
user = UserAttributes.query.filter_by(user_id=record.userid).first()
if record.targetskill == 'int':
record.isactive = 0
user.intelligence += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.intelligence, time.time()))
if record.targetskill == 'end':
record.isactive = 0
user.endurance += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.endurance, time.time()))
if record.targetskill == 'str':
record.isactive = 0
user.strength += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.strength, time.time()))
else:
pass
self.skillcheck = None
skilltime = SkillTimer()
skilltime.run()
#while True:
skilltime = SkillTimer()
skilltime.run()
#skilltimer.run()
这可以像您期望的那样完美运行,但是,在运行超过950次后,我遇到了问题。我收到如下递归错误:
Traceback (most recent call last):
File "D:\Anaconda3\lib\runpy.py", line 183, in _run_module_as_main
mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
File "D:\Anaconda3\lib\runpy.py", line 109, in _get_module_details
__import__(pkg_name)
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 52, in <module>
skilltime.run()
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 47, in run
skilltime.run()
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 47, in run
skilltime.run()
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 47, in run
skilltime.run()
[Previous line repeated 923 more times]
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 46, in run
skilltime = SkillTimer()
File "<string>", line 4, in __init__
File "D:\Anaconda3\lib\site-packages\sqlalchemy\orm\state.py", line 414, in _initialize_instance
manager.dispatch.init_failure(self, args, kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\util\langhelpers.py", line 60, in __exit__
compat.reraise(exc_type, exc_value, exc_tb)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\util\compat.py", line 187, in reraise
raise value
File "D:\Anaconda3\lib\site-packages\sqlalchemy\orm\state.py", line 411, in _initialize_instance
return manager.original_init(*mixed[1:], **kwargs)
File "D:\Anaconda3\feuadal_kingdom\app\Skilltimer.py", line 10, in __init__
self.skillcheck = SkillTracker.query.filter_by(isactive=1).all()
File "D:\Anaconda3\lib\site-packages\sqlalchemy\orm\query.py", line 2638, in all
return list(self)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\orm\query.py", line 2790, in __iter__
return self._execute_and_instances(context)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\orm\query.py", line 2813, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 945, in execute
return meth(self, multiparams, params)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 263, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\engine\base.py", line 1046, in _execute_clauseelement
if not self.schema_for_object.is_default else None)
File "<string>", line 1, in <lambda>
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 436, in compile
return self._compiler(dialect, bind=bind, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 442, in _compiler
return dialect.statement_compiler(dialect, self, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 435, in __init__
Compiled.__init__(self, dialect, statement, **kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 216, in __init__
self.string = self.process(self.statement, **compile_kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 242, in process
return obj._compiler_dispatch(self, **kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\visitors.py", line 81, in _compiler_dispatch
return meth(self, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1738, in visit_select
text, select, inner_columns, froms, byfrom, kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1822, in _compose_select_body
t = select._whereclause._compiler_dispatch(self, **kwargs)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\visitors.py", line 81, in _compiler_dispatch
return meth(self, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1025, in visit_binary
return self._generate_generic_binary(binary, opstring, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1050, in _generate_generic_binary
self, eager_grouping=eager_grouping, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\visitors.py", line 81, in _compiler_dispatch
return meth(self, **kw)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1183, in visit_bindparam
name = self._truncate_bindparam(bindparam)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1239, in _truncate_bindparam
bind_name = self._truncated_identifier("bindparam", bind_name)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1250, in _truncated_identifier
anonname = name.apply_map(self.anon_map)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\elements.py", line 4079, in apply_map
return self % map_
File "D:\Anaconda3\lib\site-packages\sqlalchemy\util\_collections.py", line 729, in __missing__
self[key] = val = self.creator(key)
File "D:\Anaconda3\lib\site-packages\sqlalchemy\sql\compiler.py", line 1269, in _process_anon
return derived + "_" + str(anonymous_counter)
RecursionError: maximum recursion depth exceeded while getting the str of an object
这杀死了进程,我不敢通过异常,因为它在那里是有原因的。
我的问题是,有没有一种方法可以调整此线程类,使其可以运行无数次?
我认为可以通过每次重新启动类线程来解决此问题,但是同样,我不确定如何创建此类无限循环。
唯一的警告是,目前我仅在测试,因此任何解决方案都应该可以通过键盘中断。
如果需要进一步说明,请告诉我,数据库模型或烧瓶路由中没有任何错误,一切都按我希望的那样完美地进行,除了达到递归限制之后的错误。例如。增大递归限制只会延迟错误,而不能解决错误。
答案 0 :(得分:1)
我会这样更改它:
import threading
from app.models import SkillTracker, UserAttributes
from flask_sqlalchemy import SQLAlchemy
from app import db
import time, math
class SkillTimer(threading.Thread, SkillTracker):
def __init__(self, SkillTracker=SkillTracker):
threading.Thread.__init__(self)
self.skillcheck = SkillTracker.query.filter_by(isactive=1).all()
def run(self):
while True:
time.sleep(1)
self.skillcheck = SkillTracker.query.filter_by(isactive=1).all()
if self.skillcheck != []:
print(self.skillcheck)
for record in self.skillcheck:
if record.isactive == 1:
if record.timesubmit + record.timetowait <= time.time():
user = UserAttributes.query.filter_by(user_id=record.userid).first()
if record.targetskill == 'int':
record.isactive = 0
user.intelligence += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.intelligence, time.time()))
if record.targetskill == 'end':
record.isactive = 0
user.endurance += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.endurance, time.time()))
if record.targetskill == 'str':
record.isactive = 0
user.strength += 1
db.session.commit()
print('User {} upgraded {}, level = {} -- {}'.format(user.user_id, record.targetskill,
user.strength, time.time()))
else:
pass
self.skillcheck = None
skilltime = SkillTimer()
skilltime.run()