我想创建一个永远运行的简单后台任务。我将找到一种方法,与我在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
这会杀死这个过程,我不敢通过例外,因为它是有原因的。
我的问题是,有没有一种方法可以调整这个线程类,以便它可以运行无限次?
我觉得这可以通过每次重新启动类线程来解决,但同样,我不完全确定如何创建这种无限循环。
唯一需要注意的是,此时我只是测试所以任何解决方案都应该可以通过键盘中断。
如果您需要进一步明确,请告诉我,数据库模型或烧瓶路径中没有任何错误,除了在达到递归限制后的错误之外,一切都能正常运行。例如。增加递归限制只会延迟错误,而不是解决它。
我会改变它:
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()