Flask - TypeError: l'objet de type cycle n'est pas sérialisable JSON
J'essaie de renvoyer une réponse json du serveur au client après que le client ait publié un message via AJAX.
Comme ça, ça marche:
@app.route("/test", methods=["GET", "POST"])
@login_required
def test():
if request.is_xhr:
try:
json_response = {
"result": "success"
}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "msg": err}
return jsonify(json_response)
else:
return redirect("/not-found")
return ''
Si j'aime ça, ça ne marche pas:
@app.route("/test", methods=["GET", "POST"])
@login_required
def test():
if request.is_xhr:
try:
_dict = {
"key1": "value1",
"key2": "value2"
}
if not "my_dict" in session:
session["my_dict"] = [_dict]
else:
session["my_dict"] = session["my_dict"] + [_dict]
session.modified = True
json_response = {
"result": "success"
}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "msg": err}
return jsonify(json_response)
else:
return redirect("/not-found")
return ''
J'obtiens l'erreur suivante et le client ne reçoit pas de réponse json:
File "~/myprojectenv/lib/python3.8/site-packages/flask/json/__init__.py", line 100, in default
return _json.JSONEncoder.default(self, o)
File "/usr/lib/python3.8/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type cycle is not JSON serializable
[2020-09-26 19:01:14,091] ERROR in app: Request finalizing failed with an error while handling an error
Si je supprime cet étirement:
if not "my_dict" in session:
session["my_dict"] = [_dict]
else:
session["my_dict"] = session["my_dict"] + [_dict]
session.modified = True
Cela fonctionne à nouveau. Le client reçoit la réponse json.
Réponses
J'ai compris le problème.
Découvrez la fonction suivante:
@app.route("/test", methods=["GET", "POST"])
def test():
if request.is_xhr:
try:
licycle = cycle(files)
nextelem = next(licycle)
_dict = {
"sid": session["_id"],
"licycle": licycle,
"nextelem": nextelem,
"licycle2": licycle2,
"nextelem2": nextelem2,
"mon_id": _id,
"sch_id": 0
}
if not "all_submons" in session:
session["all_submons"] = [_dict]
else:
session["all_submons"] = session["all_submons"] + [_dict]
session.modified = True
all_submons.setdefault("sub_mons", []).append(_dict)
json_response = {"result": "success"}
except Exception as e:
err = _except(line=sys.exc_info()[-1].tb_lineno, error=e, function_name=what_func(), script_name=__file__)
json_response = {"result": "failure", "err": err}
finally:
try:
print("exiting...")
except Exception as e:
pass
return jsonify(json_response)
else:
return redirect("/not-found")
return ""
La raison en est que le type de variable licycle est <class 'itertools.cycle'> et la session "n'accepte probablement pas" ce type de variable comme un dictionnaire accepte comme vous pouvez le voir dans ma variable dict all_submons.
Le point est:
L'exécution NE TOMBE PAS en exception. Et _dict est stocké sur la session comme vous pouvez le voir ensuite.
print(f"Session before: {session}")
print(f"all_submons before: {all_submons}")
if not "all_submons" in session:
session["all_submons"] = [_dict]
else:
session["all_submons"] = session["all_submons"] + [_dict]
session.modified = True
all_submons.setdefault("sub_mons", []).append(_dict)
print(f"Session after: {session}")
print(f"all_submons after: {all_submons}\n")
Vous pouvez vérifier la sortie:
Session before: <SecureCookieSession {'_fresh': True, '_id': 'e253a950...', 'all_submons': [], 'user_id': '1'}>
all_submons before: {}
Session after: <SecureCookieSession {'_fresh': True, '_id': 'e253a...', 'all_submons': [{'sid': 'e253a95...', 'licycle': <itertools.cycle object at 0x7fc989237280>, 'nextelem': ('1a4add0f275c7275.jpg',), 'licycle2': None, 'nextelem2': None, 'mon_id': 1, 'sch_id': 0}], 'user_id': '1'}>
all_submons after: {'sub_mons': [{'sid': 'e253a...', 'licycle': <itertools.cycle object at 0x7fd6f1a17b80>, 'nextelem': ('1a4add0f275c7275.jpg',), 'licycle2': None, 'nextelem2': None, 'mon_id': 1, 'sch_id': 0}]}
Je ne suis pas sûr que la session "n'accepte probablement pas" ce type de variable - <class 'itertools.cycle'>
Mais j'ai créé un autre dictionnaire avec d'autres variables, sans type de itertools.cycle et cela a fonctionné.