Python - возвращение результата запроса с сервера клиенту во Flask - PullRequest
0 голосов
/ 12 ноября 2018
  • Что у меня есть

    У меня есть клиент / сервер во Flask. Клиент отправляет запрос в формате JSON на сервер, а сервер создает файл JSON. Есть другой инструмент, который принимает этот запрос, выполняет его в БД и записывает результат в файл results.txt. Сервер периодически проверяет каталог 'results' на наличие файлов .txt и, если он находит новый файл, извлекает результат. Для периодической проверки я использовал APS.

  • Что я хочу сделать Теперь я хочу отправить эти данные (queryResult), которые сервер извлек из файла .txt обратно клиенту.

Это то, что я сделал до сих пор.

  • Код сервера:
app = Flask(__name__)
api = Api(app)

# Variable to store the result file count in the Tool directory
fileCount = 0

# Variable to store the query result generated by the Tool
queryResult = 0    

# Method to read .txt files generated by the Tool
def readFile():
    global fileCount
    global queryResult
    # Path where .txt files are created by the Tool
    path = "<path>"
    tempFileCount = len(fnmatch.filter(os.listdir(path), '*.txt'))
    if (fileCount != tempFileCount):
        fileCount = tempFileCount
        list_of_files = glob.iglob(path + '*.txt')
        latest_file = max(list_of_files, key=os.path.getctime)
        print("\nLast modified file: " + latest_file)
        with open(latest_file, "r") as myfile:
            queryResult = myfile.readlines()
            print(queryResult) # I would like to return this queryResult to the client

scheduler = BackgroundScheduler()
scheduler.add_job(func=readFile, trigger="interval", seconds=10)
scheduler.start()   

# Shut down the scheduler when exiting the app
atexit.register(lambda: scheduler.shutdown())   

# Method to write url parameters in JSON to a file
def write_file(response):
    time_stamp = str(time.strftime("%Y-%m-%d_%H-%M-%S"))  
    with open('data' + time_stamp + '.json', 'w') as outfile:
        json.dump(response, outfile)
    print("JSON File created!")


class GetParams(Resource):
    def get(self):
        response = json.loads(list(dict(request.args).keys())[0])  
        write_file(response)  

api.add_resource(GetParams, '/data')  # Route for GetJSON()

if __name__ == '__main__':
    app.run(port='5890', threaded=True)
  • Код клиента
data = {
    'query': 'SELECT * FROM table_name'
}

url = 'http://127.0.0.1:5890/data'

session = requests.Session()
retry = Retry(connect=3, backoff_factor=0.5)  
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

resp = session.get(url, params=json.dumps(data))
print(resp)

Может ли кто-нибудь помочь мне, как отправить этот запрос к клиенту?

EDIT: я хотел бы, чтобы сервер отправлял queryResult обратно клиенту каждый раз, когда он встречает новый файл в каталоге Tool, т. Е. Каждый раз, когда он находит новый файл, он извлекает результат (который он делает в настоящее время) и отправьте его обратно клиенту.

1 Ответ

0 голосов
/ 12 ноября 2018

То, что вы хотите сделать, называется Web Worker Architecture.

Чтобы передать реальное резюме queryResult из фонового задания клиентскому приложению, вы можете использовать комбинацию очереди сообщений (рекомендуется Kafka, RabbitMQ тоже в порядке) и веб-сокета. Когда клиент отправляет запрос к конечной точке /data, вы должны вернуть обратно некоторый уникальный токен (например, UUID, если ваш пользователь анонимный, или идентификатор пользователя, если он аутентифицирован). Тот же токен вы должны добавить к имени получившегося файла. Когда ваш фоновый работник завершил обработку файла, он использует токен (из имени файла) для создания темы Kafka или RabbitMQ, например topic_for_user_id_1337 или topic_for_uuid_jqwfoj-123qwr, и публикует queryResult в качестве сообщения.

В то же время ваш клиент должен установить соединение через веб-сокет (Flask довольно плохо подходит для веб-сокетов, но в любом случае для этого не так много хороших библиотек, как socketio) и передать токен через него на бэкэнд поэтому он создаст подписчика очереди сообщений, подписанного на тему с именем токена, поэтому, когда фоновое задание будет завершено, веб-сервер получит сообщение и передаст его пользователю через веб-сокет.

P.S. Если это звучит слишком сложно, вы можете избежать использования MQ и WS и поместить queryResult в БД и создать конечную точку, чтобы проверить, существует ли она в БД. Если это не так, вы возвращаете что-то вроде not ready yet, и клиент повторяет попытку через несколько секунд, если он готов - вы возвращаете queryResult из БД.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...