提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Windows下使用Pyinstaller打包Django项目踩过的坑
博客地址http://www.sihai.online/2024/03/06/pyinstaller/
文章目录
前言
提示:windows下部署django服务监听端口很不稳定,因为许多python的库包并不能自动导入,需要手动排查,新增模块也需要自己手动添加,尤其在app里面注册了很多服务
提示:以下是本篇文章正文内容,下面案例可供参考
一、首先安装pyinstaller
注意pyinstaller的版本,如果的端口最后监听不起来,也很有可能是pyinstaller的原因
二、打包为exe可执行文件
1.新建django项目
django-admin startproject helloworld
2.跑一下项目,确保项目可以正常运行
3.安装django-windows-tools
在app里面注册django-windows-tools,使用 python manage.py winservice_install 命令自动生成service.py和service.ini两个文件
4.修改service.py和service.ini
service.py
# !/usr/bin/env python
import os
import os.path
import sys
import win32serviceutil
import win32timezone
import traceback
import servicemanager
import winerror
import multiprocessing
import re
# This is my base path
base_path = os.path.dirname(os.path.abspath(__file__))
if getattr(sys, 'frozen', False):
base_path = sys._MEIPASS
if not base_path in sys.path:
sys.path.append(base_path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hello.settings")
from django_windows_tools.service import DjangoService, test_commands, error
class helloService(DjangoService):
_base_path = base_path
_svc_name_ = "helloService"
_svc_display_name_ = "helloService"
_svc_description_ = "helloService"
_config_filename = "service.ini"
def __init__(self, args):
DjangoService.__init__(self, args)
if __name__ == "__main__":
multiprocessing.freeze_support()
argv_len = len(sys.argv)
if argv_len > 1 and sys.argv[1] == 'test':
test_commands(base_path)
else:
if argv_len == 1:
try:
evtsrc_dll = os.path.abspath(servicemanager.__file__)
servicemanager.PrepareToHostSingle(helloService)
servicemanager.Initialize('smartLabService', evtsrc_dll)
servicemanager.StartServiceCtrlDispatcher()
except Exception as exp:
print('ERROR : %s, Detail : %s' % (exp, traceback.format_exc()))
if exp.args[0] == winerror.ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
win32serviceutil.usage()
else:
win32serviceutil.HandleCommandLine(helloService)
service.ini
[services]
# Services to be run on all machines
run=runserver
clean=d:\logs\service.log;
[BEATSERVER]
# There should be only one machine with the celerybeat service
run=celeryd celerybeat
clean=d:\logs\celerybeat.pid;d:\logs\beat.log;d:\logs\celery.log
[celeryd]
command=celeryd
parameters=-f d:\logs\celery.log -l info
[celerybeat]
command=celerybeat
parameters=-f d:\logs\beat.log -l info --pidfile=d:\logs\celerybeat.pid
[runserver]
# Runs the debug server and listen on port 8000
# This one is just an example to show that any manage command can be used
command=runserver
parameters=--noreload 0.0.0.0:8000
[log]
filename=d:\logs\service.log
level=INFO
日志我直接放到d盘了,要在d盘下建一个logs文件夹,
可以使用管理员身份调用cmd,进入项目目录,使用命令python service.py install安装,
使用python service.py start启动服务,然后使用netstat -ano|find "8000"查一下端口是否正常监听
5.使用下面的命令生成spec文件
pyi-makespec -D service.py
此时生成service.spec文件
6.注意隐式导包
在spec中需要修改以下两处
datas=[('service.ini', '.')],
hiddenimports=['django.contrib.admin.apps',
'django.contrib.auth.apps',
'django.contrib.contenttypes.apps',
'django.contrib.messages.apps',
'django.contrib.staticfiles.apps',
'django.contrib.sessions.models',
'django.contrib.sessions.apps',
'django.contrib.messages.middleware',
'django.contrib.auth.middleware',
'django.contrib.sessions.middleware',
'django.contrib.sessions.serializers',],
datas是将我们静态文件直接移动到可执行文件路径下
hiddenimports则是将django的一些包环境集成过来
7.使用pyinstaller -y service.spec
打包完成后生成可执行文件目录,cmd管理员身份进入目录,service.exe install安装,
service.exe start启动,然后检查端口是否正常监听
8.如果端口正常监听,那么恭喜你,接下来就是新增模块的问题了
新增模块
python manage.py startapp api
然后注册app,关联url,写接口,一切完成之后,开始按照上述方法重复打包
接下来是重点,然后将新增模块复制到打好的文件夹下面
注意,如果引入了第三方库,这个时候pyinstaller是不会主动将第三方库包集成过来的,需要你手动去环境中将第三方库移植过来
另外记住一定是先打包,然后再去移植文件,否则可能端口监听不起来