【问题标题】:Flask with PyInstaller does not show images added at runtime带有 PyInstaller 的 Flask 不显示在运行时添加的图像
【发布时间】:2021-06-29 19:03:53
【问题描述】:

我有一个在 Flask 上运行的简单应用程序,它显示目录中的图像。效果很好,直到我使用 Pyinstaller 创建可执行文件。当创建时已经有一些图像时,这个可执行文件也可以工作,但是它不能加载任何以后添加的图像,我猜它只是捆绑了所有现有的图像。我尝试使用单个文件和目录,但没有任何效果。 如果有人能给我一些指导,我将不胜感激。

这是html文件:

<html>
<head>
</head>
   
<body>
    <h1>Output page</h1>
    <img id="im" src="{{ url_for('static', filename=image) }}" />
</body>
<script>
    var img = document.getElementById('im');
    console.log('img.src: ' + img.src);
</script>
</html>

这是服务器代码:

import os
import requests
from flask import Flask
from flask import render_template

app = Flask(__name__)

image_no_ = 0

@app.route('/', methods = ['POST', 'GET'])
def show_image():
    global image_no_

    files = os.listdir('static/images')

    new_image = 'static/images/'+files[image_no_]
    print ('image path:', new_image)
    image_no_ += 1
    if image_no_ == len(files):
        image_no_ = 0

    return render_template("index.html", image=new_image)  

if __name__=='__main__':
    app.run(debug=True, host='127.0.0.1', port=8000)

这是我的 pyinstaller 规范文件:

# -*- mode: python ; coding: utf-8 -*-


block_cipher = None


a = Analysis(['test.py'],
             pathex=['/home/danish/Downloads/danish/code/TestFlask'],
             binaries=[],
             datas=[('templates/index.html', 'templates/'), ('static/images', 'static/images')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='test',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )

【问题讨论】:

    标签: python flask pyinstaller


    【解决方案1】:

    所以我在上面的代码中发现了两个问题。

    1. 捆绑后,pyinstaller 可执行文件会获得一个运行时本地路径,该路径存储在 sys._MEIPASS 中,因此任何文件访问都必须通过该路径。
    2. Flask 默认使用 static 作为访问图像的文件夹,但现在我们的路径已更改,因此我们需要添加一个新路径来访问这些文件:

    现在代码如下所示:-

    HTML:

    <head>
    </head>
    
    <body>
        <h1>Output page</h1>
        <img id="im" src="{{ url_for('images', filename=image) }}" />
        <button id="button" type="button" on_click=click()>next</button>
    </body>
    <script>
        var img = document.getElementById('im');
        console.log('img.src: ' + img.src);
    </script>
    </html>
    

    服务器代码:

    import os
    import sys
    import requests
    from flask import Flask
    from flask import render_template
    
    app = Flask(__name__)
    
    image_no_ = 0
    
    def resource_path(relative_path):
        """ Get absolute path to resource, works for dev and for PyInstaller """
        try:
            # PyInstaller creates a temp folder and stores path in _MEIPASS
            base_path = sys._MEIPASS
        except Exception:
            base_path = ""
        return os.path.join(base_path, relative_path)
    
    from flask import send_from_directory
    
    @app.route('/images/<path:filename>')
    def images(filename):
        valid_file_formats = ['.jpg', '.png', '.bmp']
        base_path = ""
        if filename[-4:] in valid_file_formats:
            base_path = resource_path('static/data')
        return send_from_directory(base_path, filename)
    
    @app.route('/', methods = ['POST', 'GET'])
    def show_image():
        global image_no_
    
        files_path = resource_path('static/data')
        files = os.listdir(files_path)
        new_image = files[image_no_]
    
        image_no_ += 1
        if image_no_ == len(files):
            image_no_ = 0
    
        return render_template("index.html", image=new_image)  
    
    if __name__=='__main__':
        print ('Base Path:', sys._MEIPASS)
        app.run(debug=True, host='127.0.0.1', port=8000)
    

    还必须管理不在 pyintaller 的规范文件中的一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 2018-01-18
      • 2018-12-18
      • 2013-12-16
      • 2012-03-01
      相关资源
      最近更新 更多