[PYTHON] Asynchrone Kommunikation nur mit Touch Designer

Einführung

TouchDesigner (TD) kann Python-Skripte ausführen. Wenn die Verarbeitung wie die HTTP-Kommunikation einige Zeit in Anspruch nimmt, friert sie ein wenig ein, bis die Verarbeitung abgeschlossen ist. Zu diesem Zeitpunkt wird ** auch die Zeitleiste des gesamten TD angehalten und die Zeichnung wird nicht aktualisiert ** Um dies zu verhindern, haben wir uns für eine asynchrone Kommunikation entschieden.

Wenn Sie den Wert nur asynchron erhalten möchten, können Sie zusätzlich zu TD aber auch Knoten usw. verwenden Aufgrund der Umstände der Umgebung wollte ich es nur mit TD vervollständigen, daher habe ich die folgende Methode in Betracht gezogen.

--Verwenden Sie "Web DAT" --Verwenden Sie das Threading-Modul

Ich werde jedes davon erklären.

Beispielcode

Dieses Beispiel wird unten hochgeladen. https://github.com/genkitoyama/TD_with_asynchronous_communication

Verwenden Sie "Web DAT"

Das ist am einfachsten. Wenn der Parameter "Asynchroner Abruf" aktiviert ist, Geben Sie die URL ein und drücken Sie die Schaltfläche "Abrufen". Die TD-Timeline stoppt nicht und kommuniziert hinter den Kulissen (möglicherweise Curl?). Referenz: https://docs.derivative.ca/Web_DAT

Dec-15-2019 14-18-35.gif (Im obigen Beispiel wird API zum Ermitteln der Höhe des Nationalen Landforschungsinstituts verwendet.)

Im Fall von GET ist es in Ordnung, wenn Sie es direkt in die URL eingeben. Im Fall von POST ist es in Ordnung, wenn Sie die Schaltfläche "Senden" mit der Tabelle der Daten, die Sie senden möchten, an den oberen Eingang "Eingang 0" anschließen. (Übrigens können Sie einen benutzerdefinierten HTTP-Header in den unteren Einlass einfügen.)

Ziehen Sie dann entsprechend dem Format des zurückgegebenen Elements den erforderlichen Wert mit dem Modul "XML DAT" oder "json", und fertig.

Referenz: JSON in DAT-Tabelle mit TouchDesigner analysieren

Verwenden Sie das Threading-Modul

threading Modul Ist ein Modul, das eine Multithread-Parallelverarbeitung durchführt. Es ist standardmäßig in Python 3.5 in TD enthalten.

Wenn Sie die Funktion, die Sie ausführen möchten, in einen anderen Thread und das Argument dieser Funktion in das Argument "threading.Thread ()" einfügen, wird sie in einem anderen Thread ausgeführt.

Hier wird "Anfragen" als Modul für die HTTP-Kommunikation verwendet. Anfragen sind auch standardmäßig in Python in TD enthalten. (Es gibt mehrere andere Module, die HTTP-Kommunikation durchführen, aber ich bin der Meinung, dass Sie alles verwenden können, was Sie möchten.)


import threading
import requests

class HttpRequest():
	def __init__(self):
		self.url = op('URL').text
		self.city_id = op('CITY_ID').text
	
    #Funktionen, die Sie asynchron ausführen möchten
	def request(self):
		response = requests.get(self.url, params={'city':self.city_id})
		
	def start_request(self):
		myThread = threading.Thread(target=self.request)
		myThread.start()

Dies ist ein großartiger Verweis auf Artikel von Dr. Matthew Ragan.

Nachteile und Gegenmaßnahmen

Das "Threading" -Modul ist ebenfalls sehr nützlich, hat jedoch einige Nachteile.

--Kann nicht erkennen, wann der Prozess in einem anderen Thread beendet wurde --Kann nicht auf den TD-Operator verweisen, während ein anderer Thread verarbeitet wird

Kann nicht erkennen, wenn die Verarbeitung in einem anderen Thread beendet wurde

Ich kann einen Stoppbefehl vom Hauptthread senden. Es ist nicht möglich zu erkennen, wann die Verarbeitung in einem anderen Thread abgeschlossen ist. Wenn Sie die Methode join () verwenden, können Sie auf das Ende eines anderen Threads warten. Während dieser Zeit stoppt der Haupt-Thread, sodass der TD schließlich stoppt. ..

Daher ist es nicht einfach, etwas wie "Ich habe die URL in einem anderen Thread getroffen und diesen Prozess ausgeführt, wenn der Wert zurückgegeben wird" zu tun.

Kann während der Verarbeitung eines anderen Threads nicht auf den TD-Operator verweisen

Dies ist natürlich, wenn Sie darüber nachdenken, aber da es in einem anderen Thread verarbeitet wird, Zugriff auf den Operator im Hauptthread des TD nicht möglich.

Daher ist es nicht möglich, "das zurückgegebene Ergebnis zu analysieren, indem Sie die URL in einem anderen Thread auf" Table DAT "klicken, da es sich in derselben Funktion befindet".

(Übrigens, wenn Sie das tun, erhalten Sie einen Dialog wie diesen) multi_threading_alert.png

Gegenmaßnahmen

Es ist also eine ziemliche Fähigkeit, aber ich habe mich entschieden, "Timer CHOP" zu verwenden, um zu überwachen, ob der Wert zurückgegeben wird (≒ ob die Verarbeitung eines anderen Threads abgeschlossen ist) **.

Ich möchte, dass Sie das Beispiel für Details sehen, aber grob gesagt ist der Fluss wie folgt.

  1. Schreiben Sie den Prozess zum Speichern des erhaltenen Werts in der Mitgliedsvariablen in der Funktion, die in einem anderen Thread ausgeführt werden soll.
  2. Überprüfen Sie, ob die Variable einen Wert in "onDone ()" des "Timer CHOP" -Rückrufs enthält.
  3. Wenn dies der Fall ist, endet der Timer und fährt mit einem anderen Prozess fort.
  4. Wenn nicht, starten Sie den Timer neu

Dec-15-2019 14-28-46.gif

Im obigen Beispiel wird [Weather Hacks] von livingoor (http://maps.gsi.go.jp/development/elevation_s.html) verwendet. Mit dieser API wird das Ergebnis sofort zurückgegeben. Selbst wenn Sie dies auf diese Weise tun, ist es nicht sehr lecker. Wenn es sich jedoch um die ursprüngliche API handelt, die Sie zuvor verwendet haben, dauert die Rückgabe aufgrund der Umstände 7 bis 8 Sekunden. Also habe ich diese Methode entwickelt.

Python hat versucht, die Klassen "RequestManager" und "HttpRequest" wie folgt zu erstellen.


import http_request
import json

class RequestManager():
	def __init__(self):
		self.http = http_request.HttpRequest()
		self.can_start_request = True			#Darf ich eine Anfrage stellen
		self.max_confirmation_count = 10		#Maximale Anzahl von Bestätigungen
		self.current_confirmation_count = 0		#Aktuelle Bestätigungsanzahl
		self.timer = op('timer1')
	
	def init_timer(self):
		print('init http request timer')
		
	def start_timer(self):
		#Wenn Sie eine Anfrage stellen können, werfen Sie eine Anfrage, wenn nicht, warten Sie
		if self.can_start_request == True:
			print('start http request timer')
			self.http.start_request()
		else:
			print('restart timer')
			
	def done_timer(self):
		print('done http request timer')
		#Überprüfen Sie, ob der Wert zurückgegeben wird
		output = self.http.get_data()
		#Wenn kein Wert vorhanden ist, erhöhen Sie die Anzahl der Bestätigungen und versuchen Sie es erneut
		if output is None:
			print('http response is none')
			self.can_start_request = False
			self.current_confirmation_count += 1
			#Wenn die Bestätigungsanzahl das Maximum erreicht, wird beurteilt, dass die Kommunikation fehlgeschlagen ist.
			if self.current_confirmation_count >= self.max_confirmation_count:
				print('http out of request')
				self.timer.par.initialize.pulse()
				self.http = http_request.HttpRequest()
				self.current_confirmation_count = 0
			else:
				self.timer.par.start.pulse()
		else:
		#Wenn es einen Wert gibt, wird json analysiert und gespeichert
			self.can_start_request = True
			out_json = json.loads(output)
			op('out_json')[0,0].val = out_json['forecasts'][0]
			
			self.current_confirmation_count = 0
			self.timer.par.initialize.pulse()

import threading
import requests

class HttpRequest():
	def __init__(self):
		self.url = op('URL').text
		self.city_id = op('CITY_ID').text
		self.out_data = None
		print('http request init')
	
	def request(self):
		get_data = {'city':self.city_id}
		response = requests.get(self.url, params=get_data)
		self.out_data = response.text
		print(self.out_data)
		
	def start_request(self):
		self.out_data = None
		myThread = threading.Thread(target=self.request)
		myThread.start()
		
	def get_data(self):
		return self.out_data

abschließend

――Wir haben zwei Arten von asynchronen Kommunikationsmethoden zusammengefasst, die nur TouchDesigner verwenden. ――Weil ich ein Anfänger von Python bin, wäre ich dankbar, wenn Sie den letzten Teil der Brute Force kommentieren könnten, besonders wenn Sie Ideen für eine bessere Methode haben ...!

Bonus

――Dieses Mal habe ich TouchPlayer verwendet, um jedes auf mehreren Terminals auszuführen. Da ich den Textport mit TouchPlayer jedoch nicht sehen kann, habe ich das Protokoll in eine externe Datei ausgespuckt und überprüft, ob ein Fehler aufgetreten ist.

Links, auf die verwiesen wird

Recommended Posts

Asynchrone Kommunikation nur mit Touch Designer
Verwendung von Qt Designer
Wie aktualisiere ich mit SQLAlchemy?
Wie man mit Theano besetzt
Wie mit SQLAlchemy ändern?
So trennen Sie Zeichenfolgen mit ','
Wie man RDP auf Fedora31 macht
Wie lösche ich mit SQLAlchemy?
So brechen Sie RT mit tweepy ab
Python: So verwenden Sie Async mit
So verwenden Sie virtualenv mit PowerShell
So installieren Sie Python-Pip mit Ubuntu20.04LTS
Umgang mit unausgeglichenen Daten
Wie fange ich mit Scrapy an?
Erste Schritte mit Python
Umgang mit dem DistributionNotFound-Fehler
Wie fange ich mit Django an?
Aufblasen von Daten (Datenerweiterung) mit PyTorch
So berechnen Sie das Datum mit Python
So installieren Sie den MySQL-Connector mit pip3
So verbinden Sie INNER mit SQL Alchemy
So installieren Sie Anaconda mit pyenv
So ändern Sie Djangos SQLite3, das mit nur einer grafischen Benutzeroberfläche überall auf Python hochgeladen wurde
So führen Sie eine arithmetische Verarbeitung mit der Django-Vorlage durch
[Blender] So legen Sie shape_key mit dem Skript fest
Wie man mit matplotlib mehrere Figuren betitelt
So erhalten Sie die Eltern-ID mit sqlalchemy
Python nur mit Hallo, Welten zu erinnern
So fügen Sie ein Paket mit PyCharm hinzu
So installieren Sie DLIB mit aktiviertem 2020 / CUDA
Verwendung von ManyToManyField mit Djangos Admin
Verwendung von Cmder mit PyCharm (Windows)
So verhindern Sie Paketaktualisierungen mit apt
So arbeiten Sie mit BigQuery in Python
Wie man Ass / Alembic mit HtoA benutzt
Umgang mit Enum-Kompatibilitätsfehlern
Verwendung von Japanisch mit NLTK-Plot
Wie man einen Taschentest mit Python macht
So suchen Sie in Google Colaboratory nach Google Drive
So zeigen Sie Python-Japanisch mit Lolipop an
So laden Sie YouTube-Videos mit youtube-dl herunter
Verwendung des Jupyter-Notebooks mit ABCI
So schalten Sie Linux unter Ultra96-V2 aus
Verwendung des CUT-Befehls (mit Beispiel)
Wie man mit Python-Flüchen Japanisch eingibt
So installieren Sie zsh (mit .zshrc-Anpassung)
Wie man Problemdaten mit Paiza liest
Verwendung von SQLAlchemy / Connect mit aiomysql
So gruppieren Sie Volumes mit LVM
So installieren Sie Python3 mit Docker Centos
Verwendung des JDBC-Treibers mit Redash
So löschen Sie vergangene Tweets mit Tweepy selektiv
Hochladen mit Heroku, Flask, Python, Git (4)