我有一个 Django 应用程序,它通过函数调用调用 CLI 应用程序,然后 CLI 应用程序执行操作并提供输出。CLI版本有一个加载栏,显示过程的进度,我的计划是将其与GUI集成。这个项目很大,所以我把它简化为一个较短的项目,以便你明白。真正的应用程序比这个演示应用程序更微妙和复杂
因此,我创建了一个小型演示项目来简化大家的问题。 项目结构为
│ db.sqlite3
│ manage.py
│
├───testapp
│ │ admin.py
│ │ apps.py
│ │ models.py
│ │ tests.py
│ │ views.py
│ │ views.pyc
│ │ __init__.py
│ │ __init__.pyc
│ │
│ ├───cliprog
│ │ cliprogram.py
│ │ cliprogram.pyc
│ │ main.py
│ │
│ └───migrations
│ __init__.py
│
└───testproject
settings.py
settings.pyc
urls.py
urls.pyc
wsgi.py
wsgi.pyc
__init__.py
__init__.pyc
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from cliprog.main import view_helper
def index(request):
view_helper()
return HttpResponse('It works but CLI')
cliprog/main.py
from cliprogram import nice
def view_helper(): # So, that I can call this function and run my cli code
# do something
nice()
# do something
cliprog/cliprogram.py
# Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '#'):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
"""
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print 'r%s |%s| %s%% %s' % (prefix, bar, percent, suffix)
# Print New Line on Complete
if iteration == total:
print()
#
# Sample Usage
#
from time import sleep
def nice():
# A List of Items
items = list(range(0, 57))
l = len(items)
# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
for i, item in enumerate(items):
# Do stuff...
sleep(0.1)
# Update Progress Bar
printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
因此,当您运行python manage.py runserver
时,这个想法是视图运行 CLI 程序来计算百分比(使用总值和当前样本数(。但在 CLI 上显示它,因为它是一个 CLI 程序。 现在,我需要的是我想以某种方式从 cli 文件cliprogram.py
到视图获取l
和i
(分别为总迭代和当前迭代(,视图会将其传递给 UI,我将在其中实现加载栏的 GUI 版本。
当函数nice()
被三重时,是否有可能将值传递给views.py
以便我可以更新加载栏的 GUI 版本?
注: 我已经将芹菜用于真正的应用程序。只是没有在演示应用程序中显示它。所以,如果有什么可能的话,用芹菜来解决它。非常欢迎回答
选项 1
将命令行标志添加到您的 CLI、--no-bar
或其他东西。启用--no-bar
后,不显示进度条,只打印百分比。您的 GUI 可以将百分比作为流读取并相应地更新。
注意:CLI 中的其他打印语句可能会搞砸这一点。
选项 2
将进度条打印到stderr
,但将百分比打印到stdout
。从 GUI 中只读stdout
。
因为django
本质上是单线程单进程,所以我认为您需要使用multiprocessing
或threading
库来做到这一点。您的想法涉及同时运行两段代码。您可以打开管道以在进程之间传递变量,或者如果您使用的是threading
,则可以直接读取变量。由于您给出的示例已简化,因此我不会尝试在此处修改您的代码,因为它涉及对整个项目的重大修改。
我稍微修改了你的演示,所以它可以作为一个独立的脚本运行,而不是一个django项目。但想法保持不变。
import multiprocessing as mp
# Print iterations progress
def printProgressBar (iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '#'):
"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
"""
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print('r%s |%s| %s%% %s' % (prefix, bar, percent, suffix))
# Print New Line on Complete
if iteration == total:
print()
#
# Sample Usage
#
from time import sleep
def nice(connection):
# A List of Items
items = list(range(0, 57))
l = len(items)
# Initial call to print 0% progress
printProgressBar(0, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
for i, item in enumerate(items):
# Do stuff...
sleep(0.1)
# Update Progress Bar
connection.send((i,l))
printProgressBar(i + 1, l, prefix = 'Progress:', suffix = 'Complete', length = 50)
connection.close()
def view_helper(connection): # So, that I can call this function and run my cli code
# do something
nice(connection)
# do something
def index(): # your django view
conn1,conn2=mp.Pipe()
p=mp.Process(target=view_helper,args=(conn2,))
p.start()
while True:
i,l=conn1.recv()
# do things you want with your i and l
if i==l-1:
conn1.close()
p.terminate()
break
#return HttpResponse('It works but CLI')
index()