Как передать переменную из программы CLI в представления Python для обновления пользовательского интерфейса Django?

У меня есть приложение 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, чтобы я мог обновить версию панели загрузки с графическим интерфейсом?

Примечание: Я уже использую сельдерей для настоящего приложения. Просто не показываю это в демонстрационном приложении. Итак, если что-то возможно, используйте сельдерей для ее решения. Ответы приветствуются

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
66
2

Ответы 2

Поскольку 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()

Звучит разумно. Вы можете изменить демонстрационный проект, если хотите, я постараюсь воспроизвести его и посмотреть, возможно ли его интегрировать с исходным проектом. Потому что это немного сложно.

Marcus 15.06.2018 00:39

Я уже использую сельдерей. Есть ли более функциональные возможности самого сельдерея? @pkqxdd

Marcus 15.06.2018 01:31

Я не очень знаком с сельдереем. Но я отредактировал свой ответ с помощью рабочей демонстрации.

Jerie Wang 15.06.2018 01:52

Опция 1

Добавьте флаг командной строки в свой CLI, --no-bar или что-то в этом роде. Когда --no-bar включен, вместо отображения индикатора выполнения просто выводите проценты. Ваш графический интерфейс может считывать проценты в виде потока и соответствующим образом обновлять.

Примечание: другие операторы печати в вашем CLI могут это испортить.

Вариант 2

Распечатайте индикатор выполнения в stderr, а проценты - в stdout. Читайте только stdout из вашего графического интерфейса.

Проблема в том, как получить эти значения из stdout интерфейса командной строки с помощью views.py. views.py и GUI связаны друг с другом. Итак, чтобы что-нибудь обновить в GUI. Идея состоит в том, чтобы сначала загрузить на views.py. Но самая сложная часть - это отправить данные на views.py. У тебя есть идеи на этот счет?

Marcus 15.06.2018 01:24

Другие вопросы по теме