Python 3.x 运行导入的Flask应用程序时发生ModuleNotFound错误

Python 3.x 运行导入的Flask应用程序时发生ModuleNotFound错误,python-3.x,flask,module,Python 3.x,Flask,Module,我有一个布局如下的python模块: foo | __init__.py | __main__.py | bar.py \uuuu init\uuuu.py为空 foo/bar.py的内容: from flask import Flask app = Flask(__name__) def baz(): pass from flask import Flask app = Flask(__name__) app.config["DEBUG"] = True from f

我有一个布局如下的python模块:

 foo
  |  __init__.py
  |  __main__.py
  |  bar.py
\uuuu init\uuuu.py
为空

foo/bar.py的内容

from flask import Flask
app = Flask(__name__)
def baz(): pass
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
from foo import app
app.run()
from foo import app
app.run(use_reloader=False)
当运行
python3-mfoo
时,我会得到令人困惑的结果

foo/\uuuuu main\uuuuuu.py的内容

# Results in a ModuleNotFoundError: No module named 'foo'
from foo.bar import app
app.run()

# Raises no error and correctly prints the type
from foo.bar import app
print(type(app))

# Also runs without an error
from foo.bar import baz
baz()
为什么可以从此模块导入并执行函数,但尝试对flask应用程序执行相同操作时会导致
ModuleNotFoundError
? 我看不出这有什么意义

编辑:

即使使用以下代码,错误也会持续存在:

from foo.bar import app

print(type(app))
app.run()
输出:

<class 'flask.app.Flask'>
 * Serving Flask app "foo.bar" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/home/user/projects/ftest/foo/__main__.py", line 1, in <module>
    from foo.bar import app
ModuleNotFoundError: No module named 'foo'

*服务烧瓶应用程序“foo.bar”(延迟加载)
*环境:生产
警告:不要在生产环境中使用开发服务器。
改用生产WSGI服务器。
*调试模式:打开
*继续http://127.0.0.1:5000/ (按CTRL+C退出)
*使用stat重新启动
回溯(最近一次呼叫最后一次):
文件“/home/user/projects/ftest/foo/_main__.py”,第1行,在
从foo.bar导入应用程序
ModuleNotFoundError:没有名为“foo”的模块
因此,显然可以导入模块,因为
类型(app)
工作正常,烧瓶确实启动了。这似乎是烧瓶做了重新加载和混乱的进口不知何故

编辑2:

我关闭了调试模式,效果很好。
只有当您设置了
export FLASK\u DEBUG=True
或通过
app.config[“DEBUG”]=True
显式启用调试时,才会发生此错误。事实证明,这是werkzeug中的一个错误。 如果werkzeug的重新加载程序被禁用,代码将按预期工作

如何重现这种行为

目录结构:

 foo
  |  __init__.py
  |  __main__.py
\uuuu init\uuuuu.py的内容

from flask import Flask
app = Flask(__name__)
def baz(): pass
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
from foo import app
app.run()
from foo import app
app.run(use_reloader=False)
\uuuu main\uuuuu.py的内容

from flask import Flask
app = Flask(__name__)
def baz(): pass
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
from foo import app
app.run()
from foo import app
app.run(use_reloader=False)
如果我们运行它:

$python3 -m foo
 * Serving Flask app "foo" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
Traceback (most recent call last):
  File "/home/user/projects/ftest/foo/__main__.py", line 1, in <module>
    from foo import app
ModuleNotFoundError: No module named 'foo'
一切正常

发生了什么事

问题出在
werkzeug.\u reloader.ReloaderLoop.用\u reloader重新启动\u
。它使用werkzeug.\u reloader.\u get\u args\u提供的参数调用子流程,以进行重新加载,但在通过
-m
开关执行包时,此函数的行为与预期不符

def _get_args_for_reloading():
    """Returns the executable. This contains a workaround for windows
    if the executable is incorrectly reported to not have the .exe
    extension which can cause bugs on reloading.
    """
    rv = [sys.executable]
    py_script = sys.argv[0]
    if os.name == 'nt' and not os.path.exists(py_script) and \
       os.path.exists(py_script + '.exe'):
        py_script += '.exe'
    if os.path.splitext(rv[0])[1] == '.exe' and os.path.splitext(py_script)[1] == '.exe':
        rv.pop(0)
    rv.append(py_script)
    rv.extend(sys.argv[1:])
    return rv
在我们的例子中,它返回
['/usr/local/bin/python3.7','/home/user/projects/ftest/foo/\uuuuuu main\uuuuuuuuu.py']
。这是因为
sys.argv[0]
被设置为模块文件的完整路径,但它应该返回['/usr/local/bin/python3.7','-m',foo']`(至少从我的理解来看,它应该是这样工作的)


我不知道如何纠正这种行为,或者是否需要纠正。我觉得奇怪的是,我是唯一一个遇到这个问题的人,因为这对我来说并不是一个很棘手的问题。

你在main.py文件中尝试过foo import app吗?

在app.run()之前添加以下行可以解决werkzeug重新加载程序的错误:

os.environ['PYTHONPATH'] = os.getcwd()

感谢@bootc的提示

我重新创建了您的项目,但没有看到错误,也看不到代码中出现错误的任何原因。您确定这就是您使用的代码和布局吗?您的
\uuuu init\uuuu.py
是空的还是包含代码?您从何处运行命令?re“why is可能”:Flask对参数做了一些特殊的处理;例如,如果我做了
app=Flask(“qux.baz”)
,我会得到一个失败,因为模块
qux
不存在。所以我的猜测是,要么你传递了一些奇怪的东西,要么是一些混乱的东西,比如你留下的
\uuuuPycache\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>不知怎么被坏名字锁定了…@matejcik:
\uuuuuuuuuuuuu。我正在运行上面目录中的代码。我清理了
\uuu pycache\uuuu
,这没用。我没有做任何奇怪的事情,因为帖子中的内容实际上是模块中的所有代码。您确定在执行第一个
\uuuu main\uuuu.py
代码时,您处于良好的目录中吗?(可能在顶部添加
import os;print(os.getcwd())
以进行检查)@PRMoureu它都是从同一个目录执行的。是的,在pagragraph中看到了关于复制行为的解决方案。你设置了PYTHONPATH吗?这里的更多信息,看起来像是你的问题?这确实是同一个问题,但werkzeug的人似乎也没有找到任何合理的方法来解决这个问题。但至少我现在有了解决办法。谢谢