如何在 Flask 中线程化外部挂起的 API 调用?
How Do You Thread an External Hanging API Call in Flask?
不谈细节,我正在通过 IPFS 和 Flask 编写一个开源 P2P 社交网络——我知道,它已经完成了。我选择 Flask 因为 pyinstaller 可以把它放在一个 exe 文件中。
我正在尝试每 10 分钟更新一次我的 IPNS,以发布我在上述 10 分钟内添加到网络的所有状态更新。设置 class(来自 library.py)中的 cron 函数是存储更新程序函数的地方。起初,我从设置的 init 线程化了 cron 函数。服务器挂了。然后我将线程处理移至 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 更新需要几分钟才能完成,所以我将 urllib 的超时设置为 300 秒。
好吧,我认为线程代码不正确。
@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()
,该方法开始执行并且您的应用挂起!
不谈细节,我正在通过 IPFS 和 Flask 编写一个开源 P2P 社交网络——我知道,它已经完成了。我选择 Flask 因为 pyinstaller 可以把它放在一个 exe 文件中。
我正在尝试每 10 分钟更新一次我的 IPNS,以发布我在上述 10 分钟内添加到网络的所有状态更新。设置 class(来自 library.py)中的 cron 函数是存储更新程序函数的地方。起初,我从设置的 init 线程化了 cron 函数。服务器挂了。然后我将线程处理移至 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 更新需要几分钟才能完成,所以我将 urllib 的超时设置为 300 秒。
好吧,我认为线程代码不正确。
@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()
,该方法开始执行并且您的应用挂起!