起因
Pyinstaller 打包 django 项目,打包成 manage.exe 后用命令行 cmd
manage.exe runserver 0.0.0.0:8001 --noreload 来运行感觉很不方便。
希望能够直接把命令行参数也打包进去,直接运行 exe 。我走了些弯路,但最终实现了。
弯路
我看到有人说 新建一个 main.py 在里面用 os.system :
import os
os.system('manage.exe runserver 0.0.0.0:8001 --noreload')
看起来可行,在 manage.py 外包裹一层,但我尝试以后失败了,打包出的是一个这样的结果:
运行无反应。没去深究为啥失败,毕竟对于打包我也不是太熟悉。
一种可行办法
接下来是我自己的办法。
其实也很简单,找到 main 函数,修改参数列表。
我的 Django 的 manage.py
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'src.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
注意这句:
execute_from_command_line(sys.argv)
从函数名也能知道,这是一个实现从命令行执行的函数,传入的正是 命令行参数列表 sys.argv
我们只要修改 sys.argv,就可以固定参数列表了。
但这里是有个小坑在的,如果是初学者可能会犯错。
sys.argv 是参数列表,不是字符串,所以不可以直接把 ‘runserver 0.0.0.0:8001 --noreload’ 这串字符 append 进来,而要一个个来。
所以上面代码可以改为:
) from exc
print(sys.argv)
sys.argv.append('runserver')
sys.argv.append('0.0.0.0:8001')
sys.argv.append('--noreload')
print('增加参数后:')
for a in sys.argv:
print(a, end=' ')
execute_from_command_line(sys.argv)
当然,写成列表再 append 上也行的。
argv = ['runserver', '0.0.0.0:8001', '--noreload']
sys.argv.append(argv)
然后 pyinstaller -w -F manage.py 就会生成 manage.exe 了。
不过打包成 exe ,后续可能还会遇到其它问题,比如运行起来后,资源找不到的问题,需要一一解决,manage.spec 我只能提醒一下。
后来我觉得 Django 似乎没必要打包成 exe 。。。它用作网站欸,用 dos 界面运行就行了。
第二种办法
如果不一定要生成 exe,只需要方便运行,其实 写个 bat 脚本可能更方便一些。代码都不用动。
直接加一个 bat 脚本运行 manage.py ,然后发送脚本快捷方式到桌面。
xxx.bat 脚本参考:
@echo off
REM 这里加了一个临时环境变量
set sslpath=D:\xxx\anaconda3-2020\Library\bin
set path=%sslpath%;%path%
REM 此处用全局路径会更合适,避免python升级影响。
python manage.py runserver 0.0.0.0:8001
pause
这样还会有个黑黑的 dos 界面,可能会被人不小关闭了。可以再写个 vbs 调用刚才的 bat 脚本,隐藏 dos 界面:
set shell=wscript.createObject("wscript.shell")
run=shell.Run("xxx.bat, 0)
这样的话,你想要看到进程,就只能再后台看到一个 python 进程了。