Как вы продвигаете внешний вызов API зависания в Flask? - PullRequest
1 голос
/ 05 марта 2020

Не вдаваясь в подробности, я пишу социальную сеть с открытым исходным кодом P2P через IPFS и Flask - я знаю, это было сделано. Я выбираю Flask, потому что pyinstaller может поместить его в исполняемый файл.

Я пытаюсь обновлять свой IPNS каждые 10 минут, чтобы публиковать sh все обновления статуса, которые я добавил в сеть во время указанного 10 минут. Функция cron из класса установки (из library.py) хранит эту функцию обновления. Сначала я подключил функцию cron из init установки. Сервер завис. Затем я переместил процесс создания потоков в app.before_first_request. Сервер все еще зависает.

https://pastebin.com/bXHTuH83 (main.py)

from flask import Flask, jsonify
from library import *

#=========================TO BE DELETED=========================================
def pretty(json):
    json = dumps(loads(json), indent=4, sort_keys=True)
    return json
#===============================================================================

app = Flask(__name__)

GANN = setup()

@app.before_first_request
def cron_job():
    Thread(target=GANN.cron())

@app.route("/")
def home():
    return "Hello World!!!"

if __name__ == "__main__":
    app.run(port="80", debug=True, threaded=True)

https://pastebin.com/W5P8Tpvd (library.py)

from threading import Thread
from time import time, sleep
import urllib.request
from json import loads, dumps

def api(*argv, **kwargs):
    url = "http://127.0.0.1:5001/api/v0/"
    for arg in argv:
        arg = arg.replace(" ", "/")
        if arg[:-1] != "/":
            arg += "/"
        url += arg
    url = url[0:-1]
    if kwargs:
        url+="?"
        for val in kwargs:
            url = url + val + "=" + kwargs[val] + "&"
        url = url[0:-1]
        print(url)
    try:
        with urllib.request.urlopen(url, timeout=300) as response:
            return response.read()
    except:
        return b"""{"ERROR": "CANNOT CONNECT TO IPFS!"}"""

class setup():

    def __init__(self):
        api("files", "mkdir", arg="/GANN", parents="True")
        self.root_hash = ""

    def update_root(self):
        try:
            for entry in loads(api("files", "ls", l="True").decode())["Entries"]:
                if entry["Name"] == "GANN":
                    self.root_hash = entry["Hash"]
        except:
            return """{"ERROR": "CANNOT FIND ROOT DIRECTORY"}"""

    def publish_root(self):
        api("name", "publish", arg=self.root_hash)

    def cron(self):
        while True:
            print("CRON Thread Started!")
            self.update_root()
            self.publish_root()
            sleep(600)

Я искал в Интернете пару дней и до сих пор не нашел технику потоков, которая будет отделяться от основного процесса и не зависать сервера от принятия других запросов. Я считаю, что я подключен к одному потоку, так как IPFS блокирует подключения ко всем другим устройствам в моем доме, когда он запущен. Обновление CLI IPNS до go проходит через пару минут, поэтому я установил тайм-аут urllib на 300 секунд.

1 Ответ

1 голос
/ 05 марта 2020

Ну, что я думаю, код потока не является правильным.

@app.before_first_request
def cron_job():
    Thread(target=GANN.cron())

Здесь вы создали объект Thread. Аргумент должен быть callable, но вы вызвали свой метод уже здесь. таким образом, правильный путь будет

Thread(target=GANN.cron)

Так что поток может позже вызвать функцию cron. Сказав это, Thread должен быть запущен, поэтому он вызовет функцию, которую вы задали. Так что это должен быть ike

thread_cron = Thread(target=GANN.cron)
thread_cron.start()

Поскольку вы вызвали GANN.cron(), метод начинает выполняться, и ваше приложение зависло!

...