在导入时防止来自 运行 的代码
Prevent code from running at import time
如何在 CherryPy 网络应用程序启动时导入模块而不是在创建新 Process
时获取一些代码 运行?
我的 CherryPy 应用遵循以下模式:
Main.py
from Api1.Api1 import Api1
from Api2.Api2 import Api2
config = {'global': {'server.socket_host': '0.0.0.0'}}
class Root():
global config
def __init__(self):
self.app1 = App1('app1')
self.app2 = App2('app2')
config.update(self.app1.config)
config.update(self.app2.config)
if __name__ == '__main__':
cherrypy.quickstart(Root(), '/', config)
这里 if __name__ == '__main__':
完成它的工作:__name__ == '__main__'
当服务器启动时,__name__ == '__mp_main__'
当一个新的 Process
创建时,所以 cherrypy.quickstart()
只发生一次。
App1\App1.py
def every_hour():
[...]
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
class App1():
def __init__(self, root_dir):
self.root_dir = root_dir
my_path = os.path.dirname(__file__)
self.config = {'/%s/css' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\css' % my_path},
'/%s/img' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\img' % my_path}}
这里同样的技巧不起作用,因为它总是 __name__ == 'App1.App1'
,因此在服务器启动和 Process(target=some_func).start()
时启动了一个新的 Monitor
并创建了一个新的数据库连接。
不在方法或 class 中的代码将在导入时 运行,因此如果您有一个文件 x.py 只写:
print("I'm just a poor boy, I need no sympathy")
并且你有另一个像你一样的文件导入这个文件,你甚至会在 main 或 init 启动之前看到这个文本的打印。
[编辑]回读我的回答可能有点笼统,但正因为如此,您的代码在 class 或函数之外:
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
导入时也会 运行。
一个选择是将 App1.py 顶层的初始化代码移动到一个函数中,然后从 main.py
中的 if __name__ == "__main__":
守卫内部调用该函数]:
Main.py
from App1.App1 import App1, app1_init
from App2.App2 import App2
config = {'global': {'server.socket_host': '0.0.0.0'}}
class Root():
global config
def __init__(self):
self.app1 = App1('app1')
self.app2 = App2('app2')
config.update(self.app1.config)
config.update(self.app2.config)
if __name__ == '__main__':
app1_init()
cherrypy.quickstart(Root(), '/', config)
App1.py
def every_hour():
[...]
db = None
def app1_init():
global db
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
class App1():
def __init__(self, root_dir):
self.root_dir = root_dir
my_path = os.path.dirname(__file__)
self.config = {'/%s/css' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\css' % my_path},
'/%s/img' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\img' % my_path}}
这不是很理想,因为任何导入 App1
的东西都需要知道调用 app1_init
,但它确实解决了这个问题。
如何在 CherryPy 网络应用程序启动时导入模块而不是在创建新 Process
时获取一些代码 运行?
我的 CherryPy 应用遵循以下模式:
Main.py
from Api1.Api1 import Api1
from Api2.Api2 import Api2
config = {'global': {'server.socket_host': '0.0.0.0'}}
class Root():
global config
def __init__(self):
self.app1 = App1('app1')
self.app2 = App2('app2')
config.update(self.app1.config)
config.update(self.app2.config)
if __name__ == '__main__':
cherrypy.quickstart(Root(), '/', config)
这里 if __name__ == '__main__':
完成它的工作:__name__ == '__main__'
当服务器启动时,__name__ == '__mp_main__'
当一个新的 Process
创建时,所以 cherrypy.quickstart()
只发生一次。
App1\App1.py
def every_hour():
[...]
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
class App1():
def __init__(self, root_dir):
self.root_dir = root_dir
my_path = os.path.dirname(__file__)
self.config = {'/%s/css' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\css' % my_path},
'/%s/img' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\img' % my_path}}
这里同样的技巧不起作用,因为它总是 __name__ == 'App1.App1'
,因此在服务器启动和 Process(target=some_func).start()
时启动了一个新的 Monitor
并创建了一个新的数据库连接。
不在方法或 class 中的代码将在导入时 运行,因此如果您有一个文件 x.py 只写:
print("I'm just a poor boy, I need no sympathy")
并且你有另一个像你一样的文件导入这个文件,你甚至会在 main 或 init 启动之前看到这个文本的打印。
[编辑]回读我的回答可能有点笼统,但正因为如此,您的代码在 class 或函数之外:
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
导入时也会 运行。
一个选择是将 App1.py 顶层的初始化代码移动到一个函数中,然后从 main.py
中的 if __name__ == "__main__":
守卫内部调用该函数]:
Main.py
from App1.App1 import App1, app1_init
from App2.App2 import App2
config = {'global': {'server.socket_host': '0.0.0.0'}}
class Root():
global config
def __init__(self):
self.app1 = App1('app1')
self.app2 = App2('app2')
config.update(self.app1.config)
config.update(self.app2.config)
if __name__ == '__main__':
app1_init()
cherrypy.quickstart(Root(), '/', config)
App1.py
def every_hour():
[...]
db = None
def app1_init():
global db
Monitor(cherrypy.engine, every_hour, frequency=60 * 60).start()
db = peewee.SqliteDatabase('app1.db', threadlocals=True)
class App1():
def __init__(self, root_dir):
self.root_dir = root_dir
my_path = os.path.dirname(__file__)
self.config = {'/%s/css' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\css' % my_path},
'/%s/img' % root_dir: {'tools.staticdir.on': True, 'tools.staticdir.dir': '%s\img' % my_path}}
这不是很理想,因为任何导入 App1
的东西都需要知道调用 app1_init
,但它确实解决了这个问题。