我正在使用Flask开发网站,在开发过程中,我使用以下文件运行烧瓶:
#!/usr/bin/env python
from datetime import datetime
from app import app
import config
if __name__ == '__main__':
print '################### Restarting @', datetime.utcnow(), '###################'
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0')
当我启动服务器时,或者由于文件已更新而自动重启时,它总是显示两次打印行:
################### Restarting @ 2014-08-26 10:51:49.167062 ###################
################### Restarting @ 2014-08-26 10:51:49.607096 ###################
虽然这不是一个真正的问题(其余部分按预期工作),但我只是想知道它为什么会这样?有什么想法吗?
答案 0 :(得分:111)
Werkzeug重新加载器会生成一个子进程,以便每次代码更改时都可以重新启动该进程。当您致电app.run()
时,Werkzeug是向Flask提供开发服务器的库。
见restart_with_reloader()
function code;您的脚本将使用subprocess.call()
再次运行。
如果您将use_reloader
设置为False
,您会看到该行为消失,但您也会失去重新加载功能:
app.run(port=4004, debug=config.DEBUG, host='0.0.0.0', use_reloader=False)
您也可以在使用flask run
命令时禁用重新加载器:
FLASK_DEBUG=1 flask run --no-reload
如果要检测何时处于重新加载子进程中,可以查找WERKZEUG_RUN_MAIN
环境变量:
import os
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
print '################### Restarting @ {} ###################'.format(
datetime.utcnow())
但是,如果你需要设置模块全局变量,那么你应该在函数上使用@app.before_first_request
decorator并让该函数设置这样的全局变量。当第一个请求进入时,它会在每次重新加载后被调用一次:
@app.before_first_request
def before_first_request():
print '########### Restarted, first request @ {} ############'.format(
datetime.utcnow())
请注意,如果在使用分叉或新子进程处理请求的完整WSGI服务器中运行此服务器,则可以为每个新子进程调用before_first_request
个处理程序
答案 1 :(得分:8)
如果您使用的是现代flask run
命令,则不会使用app.run
的任何选项。要完全禁用重新加载器,请传递--no-reload
:
FLASK_DEBUG=1 flask run --no-reload
此外,__name__ == '__main__'
永远不会成立,因为应用程序不会直接执行。使用Martijn's answer中的相同提示,但不包含__main__
块。
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
# do something only once, before the reloader
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
# do something each reload
答案 2 :(得分:6)
我遇到了同样的问题,我通过将app.debug
设置为False
来解决这个问题。将其设置为True
会导致我的__name__ == "__main__"
被调用两次。
(我会将此作为评论发布,但我没有足够的代表。作为答案发布,希望它可以帮助其他人)
答案 3 :(得分:1)
我正在使用插件 - python-dotenv 我会把它放在我的配置文件中 - .flaskenv:
FLASK_RUN_RELOAD=False
这将避免我的烧瓶运行两次。
答案 4 :(得分:0)
Flask应用程序运行两次的可能原因之一是在Heroku上配置了WEB_CONCURRENCY
。要设置为一个,可以在控制台中编写
heroku config:set WEB_CONCURRENCY=1
答案 5 :(得分:0)
从Flask 0.11开始,建议使用flask run
而不是python application.py
运行您的应用。使用后者可能会导致您的代码运行两次。
...从Flask 0.11开始,建议使用长瓶法。这样做的原因是,由于重载机制是如何工作的,所以存在一些奇怪的副作用(例如两次执行某些代码...)
答案 6 :(得分:-1)
我有同样的问题。我通过修改我的main并将use_reloader = False插入其中来解决了它。如果有人在寻找解决此问题的方法,那么下面的代码将帮助您入门,但是您将无法自动检测到代码更改并重新启动应用程序,因此该功能将不起作用。每次编辑代码后,您都必须手动停止并重新启动应用程序。
Private Function CreateFolder(ByVal sPath As String) As Boolean
'by Patrick Honorez - www.idevlop.com
'checks for existence of a folder and create it at once, if required
'returns False if folder does not exist and could NOT be created, True otherwise
'sample usage: If CreateFolder("C:\toto\test\test") Then debug.print "OK"
'updated 20130422 to handle UNC paths correctly ("\\MyServer\MyShare\MyFolder")
Dim fs As Object
Dim FolderArray
Dim Folder As String, i As Integer, sShare As String
If Right(sPath, 1) = "\" Then sPath = Left(sPath, Len(sPath) - 1)
Set fs = CreateObject("Scripting.FileSystemObject")
'UNC path ? change 3 "\" into 3 "@"
If sPath Like "\\*\*" Then
sPath = Replace(sPath, "\", "@", 1, 3)
End If
'now split
FolderArray = Split(sPath, "\")
'then set back the @ into \ in item 0 of array
FolderArray(0) = Replace(FolderArray(0), "@", "\", 1, 3)
On Error GoTo hell
'start from root to end, creating what needs to be
For i = 0 To UBound(FolderArray) Step 1
Folder = Folder & FolderArray(i) & "\"
If Not fs.FolderExists(Folder) Then
fs.CreateFolder (Folder)
End If
Next
CreateFolder = True
hell:
End Function