У меня есть приложение Django, которое вызывает приложение CLI с помощью вызова функции, а затем приложение CLI выполняет действие и выводит результат. Версия CLI имеет полосу загрузки, которая отображает ход процесса. Я планирую интегрировать ее с графическим интерфейсом. Проект огромен, поэтому я упростил его до более короткого, чтобы вам было понятно. Настоящее приложение более тонкое и сложное, чем это демонстрационное приложение.
Итак, я создал крошечный демонстрационный проект, чтобы упростить вопрос для всех вас. Структура проекта
│ 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, идея состоит в том, что View запускает программу CLI, которая вычисляет процент (используя общие значения и текущее количество выборок). Но отображает его в интерфейсе командной строки, поскольку это программа интерфейса командной строки.
Теперь мне нужно как-то получить l и i (общая и текущая итерация соответственно) из cli-файла cliprogram.py в представления, а представления передадут его в пользовательский интерфейс, где я буду реализовывать версию панели загрузки с графическим интерфейсом.
Есть ли возможность, который при срабатывании функции nice() может передавать значения в views.py, чтобы я мог обновить версию панели загрузки с графическим интерфейсом?
Примечание: Я уже использую сельдерей для настоящего приложения. Просто не показываю это в демонстрационном приложении. Итак, если что-то возможно, используйте сельдерей для ее решения. Ответы приветствуются






Поскольку 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()
Я уже использую сельдерей. Есть ли более функциональные возможности самого сельдерея? @pkqxdd
Я не очень знаком с сельдереем. Но я отредактировал свой ответ с помощью рабочей демонстрации.
Опция 1
Добавьте флаг командной строки в свой CLI, --no-bar или что-то в этом роде. Когда --no-bar включен, вместо отображения индикатора выполнения просто выводите проценты. Ваш графический интерфейс может считывать проценты в виде потока и соответствующим образом обновлять.
Примечание: другие операторы печати в вашем CLI могут это испортить.
Вариант 2
Распечатайте индикатор выполнения в stderr, а проценты - в stdout. Читайте только stdout из вашего графического интерфейса.
Проблема в том, как получить эти значения из stdout интерфейса командной строки с помощью views.py. views.py и GUI связаны друг с другом. Итак, чтобы что-нибудь обновить в GUI. Идея состоит в том, чтобы сначала загрузить на views.py. Но самая сложная часть - это отправить данные на views.py. У тебя есть идеи на этот счет?
Звучит разумно. Вы можете изменить демонстрационный проект, если хотите, я постараюсь воспроизвести его и посмотреть, возможно ли его интегрировать с исходным проектом. Потому что это немного сложно.