Hallo. Ich bin ein Softwareentwickler, der verschiedene Dinge wie Einbetten, Spiele, Web-Apps, iOS-Apps und Beschilderungssteuerungssysteme herstellt. Vor ungefähr zweieinhalb Jahren dachte ich als universelle Skriptsprache, dass es in Python geschrieben werden sollte, dass es schwierig ist, nur mit der Shell zu realisieren, und ich versuchte, Python zu lernen, während ich litt. Ich benutze es nur gelegentlich, deshalb vergesse ich jedes Mal, wie man if- und for-Schleifen schreibt.
Vor ungefähr anderthalb Jahren erfuhr ich jedoch, dass es in einem Buch über maschinelles Lernen und Datenwissenschaft eine REPL namens Jupyter Notebook gibt, und als ich versuchte, sie durch Ausprobieren zu verwenden, war sie nicht auf maschinelles Lernen und Datenwissenschaft beschränkt. Ich fand, dass es für alle Aufgaben geeignet ist, die tägliches Ausprobieren erfordern, und ich schreibe diesen Artikel, um ihn zu verbreiten.
Jupyter Notebook hat ein starkes Bild der Datenanalyse.
Sie benötigen jedoch keine Echtzeitmerkmale wie das Senden eines Pakets, die Verwendung als Taschenrechner für komplizierte Aufgaben, das Konvertieren verschiedener Dateiformate, das Kopieren komplizierter Dateien usw. Sie dürfen dies nur einmal tun. Es ist sehr gut geeignet, um verschiedene Dinge zu tun, wie es sein mag, aber es kann mehr als eine Zeit geben. Sie können ein Skript schreiben, indem Sie es Satz für Satz versuchen und prüfen, ob das Ergebnis wie erwartet oder falsch ist, wie z. B. die Schrittausführung, sodass Sie schnell und mit hoher Zuverlässigkeit Code schreiben können.
Wenn Sie ein Programm in einer dynamischen Sprache schreiben, gibt es einen Nachteil, dass Sie dazu neigen, Code in einem Zustand zu schreiben, in dem die Vervollständigung nicht so gut funktioniert, aber im Fall von Jupyter Notebook, während Sie die materialisierte Instanz direkt untersuchen Da Sie Methoden und Felder vervollständigen können, funktioniert die Vervollständigung ebenso wie statische Typsprachen, und Sie können viel Zeit sparen, um die Referenz zu lesen.
Diesmal,
Ich werde die vier Genres von erklären.
Bei der Erstellung von Software gibt es einige Situationen, in denen Sie eine Verhaltensanalyse auf einer Skala durchführen müssen, die von einem Debugger nicht verfolgt werden kann, oder wenn Sie Nachforschungen anstellen müssen, die mit vorhandenen Tools nicht durchgeführt werden können. Geräte, die von TCP oder UDP gesteuert werden können sollen, werden manchmal gebeten, dies zu untersuchen, da sie nicht gesteuert werden können, oder ich möchte beiläufig überprüfen, welchen Wert die Sensordaten zurückgeben, ohne die Spezifikationen zu berücksichtigen. Einige Zeichen können in einer bestimmten Schriftart angezeigt werden, andere nicht. Daher wurde ich gebeten, den Zeichenbereich festzulegen, der im System verwendet werden kann.
Grundsätzlich müssen Sie das Protokoll analysieren oder die Metadaten lesen und etwas dagegen tun, aber mit Jupyter ist es bequem, mit der Ad-hoc-Überprüfung fortzufahren.
Wir erhielten eine Anfrage zur Untersuchung des Problems, dass das von TCP / UDP gesteuerte Gerät manchmal nicht gesteuert werden konnte, und untersuchten, ob die Ursache auf der Seite der Steuerungssoftware, des Netzwerks oder der Geräteseite lag. Ich musste etwas tun. Vorläufig dachte ich, dass es möglich sein würde, etwas zu tun, indem man sich die Kommunikation ansieht. Deshalb bat ich ihn, einen Switch-Hub vorzubereiten, der Port-Spiegelung ermöglicht, und mit tshark, einem Befehlszeilen-Tool von Wireshark, täglich Pakete mit mehreren GB-Levels zu sammeln. Konvertieren Sie die erhaltene Erfassungsdatei und die .pcap-Datei mit dem folgenden Code in Pandas DataFrame.
def makeDfFromPcap(filename):
p = dpkt.pcapng.Reader(open(filename, 'rb'))
dDict = {'t':[], 'src':[], 'dst':[], 'type':[], 'srcport':[], 'dstport':[], 'length':[]}
count = 0
for ti,buf in p:
try:
eth = dpkt.ethernet.Ethernet(buf)
except dpkt.NeedData:
pass
if type(eth.data) == dpkt.ip.IP:
ip = eth.data
src = ip.src
dst = ip.dst
src_a = socket.inet_ntoa(src)
dst_a = socket.inet_ntoa(dst)
t = 'IP'
srcPort = 0
dstPort = 0
if type(ip.data) == dpkt.udp.UDP:
srcPort = ip.data.sport
dstPort = ip.data.dport
t = 'UDP'
elif type(ip.data) == dpkt.tcp.TCP:
srcPort = ip.data.sport
dstPort = ip.data.dport
t = 'TCP'
dDict['t'].append(ti)
dDict['src'].append(src_a)
dDict['dst'].append(dst_a)
dDict['type'].append(t)
dDict['srcport'].append(srcPort)
dDict['dstport'].append(dstPort)
dDict['length'].append(ip.len)
count += 1
if count % 10000 == 0:
print(count)
df = pd.DataFrame(dDict, columns=['t','src','dst','type','srcport','dstport','length'])
return df
df = makeDfFromPcap('cap_00001_20191216.pcap')
df
Danach können Sie überprüfen, wie viel Kommunikation zwischen der Quell-IP-Adresse und der Ziel-IP-Adresse stattfindet, indem Sie mit DataFrame gruppieren und summieren.
pd.DataFrame(df.groupby(['src','dst'])['length'].sum().sort_values(ascending=False) * 8 / (df.t.max() - df.t.min()))
#Band benutzt(Einheit: bps)
pd.DataFrame(df.groupby(['src','dst']).size().sort_values(ascending=False) / (df.t.max() - df.t.min()))
#Anzahl der Pakete pro Zeiteinheit(Einheit: tps)
In diesem Fall scheint die Kommunikation zwischen 10.100.45.26 und 10.100.45.39 häufig zu erfolgen. Haben Sie also nur für den Fall einen Hub, der nur 10.100.45.26 und 10.100.45.39 verbindet, die vom Haupt-Hub kaskadiert sind, und das Problem ist Ich habe den Übergang beobachtet, um zu sehen, ob
Natürlich denke ich, dass es viele Tools gibt, mit denen Pakete dieser Ebene zusammengefasst werden können, aber der große Vorteil war, dass Sie, wenn Sie Kenntnisse über Pandas hätten, nicht lernen müssten, wie man spezielle Tools verwendet.
Ich denke, dass es viele Fälle gibt, in denen Sie ein Gefühl dafür bekommen möchten, was die Sensordaten des Geräts zurückgeben, und dann mit der vollständigen Implementierung fortfahren möchten. Es musste schnell untersucht werden, wie die Werte des am IoT-Gerät angebrachten 3-Achsen-Erdmagnetsensors mit der Drehung des Geräts zusammenhängen und welche Art der Datenverarbeitung durchgeführt werden sollte, wenn Sie die Ausrichtung extrahieren möchten. .. Glücklicherweise gab es einen Beispielcode für den geomagnetischen Sensor, der die Sensordaten seriell ausgab. Deshalb habe ich beschlossen, das Textprotokoll mit TeraTerm zu speichern und zu visualisieren.
Weil es sich um solche Protokolldaten handelt
def parse_mag_str(line):
try:
splitted = line[5:].replace(' ', '').split(',')
return [float(n) for n in splitted]
except:
return None
Lassen Sie uns eine geeignete perspektivische Funktion wie erstellen.
Das Verhalten scheint also in Ordnung zu sein
mags = [parse_mag_str(l) for l in log[2:]][0:-1]
Lassen Sie uns ein Float-3D-Array erstellen.
Wenn Sie die Daten anschließend in eine interaktive 3D-Visualisierungsbibliothek wie ipyvolume einfügen, können Sie sie einfach mit der Maus in ein 3D-Diagramm konvertieren. Du kannst nachschauen.
import ipyvolume as ipv
start = 250
end = 8000
t = np.array(range(start,end))
x = np.array([m[0] for m in mags[start:end]])
y = np.array([m[1] for m in mags[start:end]])
z = np.array([m[2] for m in mags[start:end]])
x_n = np.array([m[0] for m in mags[start+10:end+10]])
y_n = np.array([m[1] for m in mags[start+10:end+10]])
z_n = np.array([m[2] for m in mags[start+10:end+10]])
u = x_n - x
v = y_n - y
w = z_n - z
ipv.figure()
quiver = ipv.quiver(x, y, z, u, v, w, size=3, size_selected=20)
ipv.show()
In diesem Fall habe ich festgestellt, dass ich nur die Koordinatenwerte der xy-Ebene atan2 muss, um die Ausrichtung zu erhalten. Da die Zeitreihe der Daten auch durch die Richtung des Kegels bekannt ist, kann das Vorzeichen richtig eingestellt werden.
Viele Pakete, die mit ipy beginnen, sind nützlich, weil sie die Sichtbarkeit und Interaktivität von Jupyter verbessern. Es gibt ipyleaflet, das Daten auf einer interaktiven Karte anzeigen kann, ipywidgets, die eine Benutzeroberfläche mit Schaltflächen erstellen können usw.
Wenn Sie das Protokoll umfassend überprüfen und das Ausgabeergebnis der Datenverarbeitung visualisieren / aussprechen müssen, scheint das Schreiben eines Verarbeitungswerkzeugs bis jetzt problematisch zu sein (nur wenn es wirklich notwendig ist). (Ich habe es mit openFrameworks geschrieben), aber ich habe mich mit einer Verifizierung getäuscht, ohne viel zu tun, aber auf dem Gebiet der Datenanalyse und -visualisierung, dem Hauptpunkt von Jupyter Notebook, können die meisten Dinge reibungslos erledigt werden, und mein Verstand ist nervös. Sie können einen Schritt nach vorne machen, um das Problem zu lösen, ohne es zu verwenden. Da das Ergebnis von Versuch und Irrtum ohne Erlaubnis als Notizbuch verbleibt, ist es sehr zeit- und arbeitsaufwendig, wenn Sie es später erneut mit anderen Daten überprüfen müssen. Ich mag es, Metadaten für Nachforschungen zu protokollieren und zu extrahieren. Wenn ich den Code in einer Atmosphäre schreibe, kann ich einen Umfragebericht erstellen, der über die manuelle Überprüfung hinausgeht, die ich bisher nur ungern mit überwältigender Genauigkeit und Quantität durchgeführt habe, und ich habe das Gefühl, etwas erreicht zu haben.
Haben Sie jemals ein UI-Design implementiert und die gleiche Multiplikation und Addition entsprechend der Bildschirmgröße basierend auf der Designzeichnung viele Male erlebt? Wenn Sie eine Bildverarbeitung durchführen und eine kleine Matrixberechnung (inverse Matrix, Diagonalisierung usw.) durchführen möchten, möchten Sie eine Rotationsmatrix in Ihrer bevorzugten Rotationsreihenfolge erstellen. Eine etwas komplizierte inverse Matrix ist algebraisch Gibt es etwas, wonach Sie fragen möchten?
Es ist notwendig, das Farbsehen einer Person mit Farbsehstörungen zu reproduzieren und nach der Konvertierung des RGB-Farbraums in den LMS-Farbraum (es handelt sich um eine lineare Konvertierung) eine Matrixoperation im LMS-Farbraum durchzuführen und in den RGB-Raum zurückzukehren. Als Ergebnis mussten wir herausfinden, welche Art der linearen Konvertierung im RGB-Farbraum durchgeführt werden sollte. Die Formel lautet wie folgt.
\begin{eqnarray}
\mathbf{c^{'}}_\mathrm{RGB} & = & \mathbf{M}_\mathrm{LMStoRGB} \cdot \mathbf{M}_\mathrm{protanopia} \cdot \mathbf{M}_\mathrm{RGBtoLMS} \cdot \mathbf{c}_\mathrm{RGB} \\
& = & ( \mathbf{M}^{-1}_\mathrm{RGBtoLMS} \cdot \mathbf{M}_\mathrm{protanopia} \cdot \mathbf{M}_\mathrm{RGBtoLMS}) \cdot \mathbf{c}_\mathrm{RGB}
\end{eqnarray}
Sie müssen nur den in Klammern auf der rechten Seite eingeschlossenen Matrixteil berechnen. Fügen Sie ihn also fast so wie er ist in Numpy ein und er wird mit dem folgenden Code vervollständigt.
import numpy as np
rgb2lms = np.array([0.31399022, 0.63951294,
0.04649755, 0.15537241, 0.75789446, 0.08670142, 0.01775239,
0.10944209, 0.87256922]).reshape((3,3))
lms2rgb = np.linalg.inv(rgb2lms)
Während ich überprüfte, ob rgb2lms und lms2rgb richtig gemacht wurden (ich wusste nicht, ob Numpy Column Major oder Row Major ist, also fuhr ich fort, während ich Jupyter überprüfte). Die resultierende Matrix könnte unten berechnet werden.
protanopia = np.array([0.0, 1.05118294,-0.05116099, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]).reshape((3,3))
lms2rgb.dot(protanopia).dot(rgb2lms)
Ich denke, dass die Rotationsmatrix im 3D-Raum häufig verwendet wird, wenn Spiele erstellt, Koordinaten mit 3DCG verarbeitet und der Bewegungssensor eines Smartphones berührt werden. Abhängig von der Reihenfolge, in der die X-, Y- und Z-Achse gedreht werden, gibt es 6 Rotationsmatrizenmuster. Bis jetzt habe ich viel verschwendet, indem ich Wikipedia einzeln durchsucht und gesagt habe, dass das, das ich ausgewählt habe, falsch ist und nicht funktioniert. Tatsächlich ist es jedoch am zuverlässigsten und schnellsten, von links nacheinander zu multiplizieren, während genau erfasst wird, wie der Vektor vom lokalen Koordinatensystem in das globale Koordinatensystem konvertiert wird. Deshalb berechne ich auch die Rotationsmatrix selbst. Nur in Python gibt es eine Bibliothek namens Sympy, die algebraische Berechnungen durchführt.
from sympy import *
#Drehung der x-Achse
theta = Symbol('theta')
Rx = Matrix([[1, 0, 0], [0, cos(theta), -sin(theta)], [0, sin(theta), cos(theta)]])
#Drehung in Richtung der y-Achse
yaw = Symbol('yaw')
Ry = Matrix([[cos(yaw), 0, sin(yaw)], [0, 1, 0], [-sin(yaw), 0, cos(yaw)]])
#Drehung der Z-Achse
phi = Symbol('phi')
Rz = Matrix([[cos(phi), -sin(phi), 0], [sin(phi), cos(phi), 0], [0, 0, 1]])
R = Ry * Rx * Rz
R
Das Ergebnis wird auch in einer schönen Form angezeigt, die mit TeX gerendert wurde, sodass es leicht zu überprüfen ist. Da ich die Rotationsmatrix selbst erstelle, versuchen Sie, die Reihenfolge zu ändern oder die Rotationsmatrix um eins zu reduzieren, auch wenn etwas nicht stimmt. Das können Sie leicht tun.
Ich habe die Anforderung erhalten, ein Bild von Projektionskonvertierung ohne Bibliothek auf einem IoT-Gerät anzuzeigen. Es war. Der Ableitungsprozess ist nicht das Hauptthema, daher werde ich ihn weglassen (obwohl das Format etwas anders ist, handelt es sich im Wesentlichen um Homographie - Shogo Computing Laboratory. Dieselbe Berechnung sollte durchgeführt werden), aber als Ergebnis wurde jedes Element der 3-mal-3-Projektionstransformationsmatrix zu einem 9-dimensionalen Vektor, als die inverse Matrix der folgenden 9-mal-9-Matrix gelöst und mit dem Vektor multipliziert wurde. Sie können das Ding X finden.
from sympy import *
# x0 = Symbol('x0')Substitution wie x0- x3, y0 -Tun Sie für y3
for i in range(4):
for c in "xy":
globals().update({c + str(i): Symbol(c + str(i))})
u0 = 640
v0 = 0
u1 = 640
v1 = 480
u2 = 0
v2 = 480
u3 = 0
v3 = 0
A = Matrix([
[ x0, y0, 1, 0, 0, 0, -x0*u0, -y0*u0, 0 ],
[ 0, 0, 0, x0, y0, 1, -x0*v0, -y0*v0, 0 ],
[ x1, y1, 1, 0, 0, 0, -x1*u1, -y1*u1, 0 ],
[ 0, 0, 0, x1, y1, 1, -x1*v1, -y1*v1, 0 ],
[ x2, y2, 1, 0, 0, 0, -x2*u2, -y2*u2, 0 ],
[ 0, 0, 0, x2, y2, 1, -x2*v2, -y2*v2, 0 ],
[ x3, y3, 1, 0, 0, 0, -x3*u3, -y3*u3, 0 ],
[ 0, 0, 0, x3, y3, 1, -x3*v3, -y3*v3, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 1 ],
])
A
B = Matrix([u0, v0, u1, v1, u2, v2, u3, v3, 1])
B
X = A.inv() * B
Es scheint, dass es in etwa 5 Sekunden berechnet werden könnte. Es scheint jedoch, dass jedes Element von X viele Begriffe enthält. Wenn Sie versuchen, es anzuzeigen, wird das Kompilieren von TeX viel Zeit in Anspruch nehmen, sodass ich es als Zeichenfolge extrahieren werde.
X_strs = [str(simplify(X[i])) for i in range(9)]
Es dauerte fast 2 Minuten, wahrscheinlich weil die Vereinfachung lange gedauert hat. Ich möchte es so wie es ist in C-Code konvertieren, also benenne ich den Begriff x0 ** 2 in x0p2 um.
list(zip([v + str(i) + '**2' for v in 'xy' for i in range(4)],[v + str(i) + 'p2' for v in 'xy' for i in range(4)]))
Es scheint, dass wir es so umbenennen können, also werden wir es sofort durch Reduzieren ersetzen.
X_strs2 = [functools.reduce(lambda s, t: s.replace(*t), list(zip([v + str(j) + '**2' for v in 'xy' for j in range(4)],[v + str(j) + 'p2' for v in 'xy' for j in range(4)])), X_strs[i]) for i in range(9)]
Die endgültige Konvertierung in C-Code erfolgt mit folgendem Code:
for v in 'xy':
for i in range(4):
print('float %s%dp2 = %s%d * %s%d;\n' % (v, i, v, i, v, i))
for i in range(9):
print('float X%d = ' % i + X_strs2[i] + ';\n')
Jetzt wird die Projektionskonvertierungsfunktion mit beliebigen Parametern für eingebettete Geräte in einer Form erstellt, die von keiner Bibliothek abhängig ist. An einer Stelle gab es eine Konvertierungsauslassung, aber als ich sie korrigierte, funktionierte sie wie erwartet.
Ich fand auch die Umkehrung dieser Projektionstransformationsmatrix mit einem ähnlichen Gefühl.
Es ist einfach, denn wenn Sie die Formel fast so schreiben, wie sie ist, wird sie vervollständigt.
Es wird auch verwendet, um die Größe von UI-Elementen zu berechnen, die mit unterschiedlichen Bildschirmgrößen entworfen wurden. Es ist nicht wirklich eine große Sache, aber ich bin froh, dass es leicht zu sehen und zu reparieren ist.
Ich mache ein Beschilderungssteuerungssystem, und ein bestimmtes Leistungssteuerungsgerät sollte mit UDP-Binärpaketen funktionieren. Deshalb habe ich versucht, ein Paket gemäß den Spezifikationen zu erstellen und es per UDP zu senden.
Machen Sie zuerst ein Paket.
switches = [True, False, True, True, False]
model_id = 3 # LA-5R
unit_id = 0b00001111 ^ 0
def make_send_bytes(model_id, unit_id, switches):
return bytes([0xf0 | unit_id, switches[4] << 4 | switches[3] << 3 | switches[2] << 2 | switches[1] << 1 | switches[0]])
send_bytes = make_send_bytes(model_id, unit_id, switches)
[format(send_bytes[i], '02x') for i in [0, 1]]
Es scheint, dass das Paket erstellt wurde, also werde ich es tatsächlich senden.
switches = [random.random() < 0.5 for i in range(0, 5)]
send_bytes = make_send_bytes(model_id, unit_id, switches)
[format(send_bytes[i], '02x') for i in [0, 1]]
s.sendto(send_bytes, (HOST, PORT))
Ich kann keine Screenshots erstellen, konnte jedoch bestätigen, dass dies funktioniert, wenn ich ein Paket sende.
Überprüfen Sie als nächstes, ob das Ein- und Ausschalten aller 5-Kanal-Muster und 32-Muster gesteuert werden kann.
sl = 0.08
l = 0.08 / sl
for j in range(0, int(l)):
for i in range(0, 32):
switches = [c == '1' for c in format(i, '05b')]
send_bytes = make_send_bytes(model_id, unit_id, switches)
[format(send_bytes[i], '02x') for i in [0, 1]]
s.sendto(send_bytes, (HOST, PORT))
time.sleep(sl)
Wenn man nur das Ergebnis des Schreibens betrachtet, ist es fast dasselbe wie das Schreiben in C, aber ohne daran gewöhnt zu sein, Bit-Arithmetik, Versuch und Irrtum, ob das Paket korrekt erstellt wurde oder nicht, es tatsächlich zu senden und zu versuchen, es zu funktionieren Es stellt sich heraus, dass die schnelle Schleife von sehr wichtig für die Implementierungseffizienz ist.
Gleichzeitig habe ich auch die Steuerung über die TCP-Verbindung überprüft. Wenn Sie dem Notizbuch jedoch eine Tabelle hinzufügen, befindet sich diese nicht in einem Zustand voller mysteriöser Kommentare, sodass Sie die Teile sortieren können, die zwischen TCP und UDP umgeleitet werden können, und die Teile, die nicht umgeleitet werden können. , Sie können später zurückblicken und die Verwendung des Codes vereinfachen.
Dies kann der typischste Fall sein. Als Softwareentwickler gibt es viele Fälle, in denen Sie ein einfaches Skript schreiben und verschiedene Formatkonvertierungen lösen möchten, um die Rohstoffdaten abzurufen und zum endgültigen Formular zu machen. Selbst in einem solchen Fall ist die Stärke von Jupyter Notebook, dass Sie versuchen können, Fehler zu machen, während Sie es betrachten, sehr nützlich.
Während der Spieleentwicklung wollte ich manchmal Bilder portieren, die mithilfe der 3D-Ebenenfunktion in After Effects in Unity platziert wurden. Natürlich kann dies realisiert werden, indem ein Unity Quad-Objekt erstellt wird, während die numerischen Werte schichtweise betrachtet werden, aber ich möchte keine so einfache Aufgabe ausführen, obwohl es ungefähr 50 Ebenen gibt. Also habe ich zuerst alle Informationen der After Effects-Ebene in JSON mit ESTK geschrieben und dann in Jupyter Notebook verarbeitet.
Überprüfen Sie zunächst, welcher Wert enthalten ist.
import json
import codecs
from operator import itemgetter
with codecs.open('transforms.json', 'r', encoding='shift-jis') as f:
root = json.load(f)
root
Nehmen Sie eine Schicht heraus,
layer = root['9']
layer
Position, Ankerpunkt, Breite, Höhe, Maßstab usw. werden für jedes Element von X und Y zusammengefasst.
list(zip(layer['Position'],layer['Ankerpunkt'],[layer['width'], layer['height']], [layer['Rahmen'][0], layer['Rahmen'][1]]))
Wir werden die Positionsspezifikation und Vergrößerung / Verkleinerung, die die Ankerpunktkriterien sind, als zentrale Referenz verwenden.
[ps[0] - ps[1] * ps[3] + ps[2] * ps[3] / 2 for ps in zip(
layer['Position'],
layer['Ankerpunkt'],
[layer['width'], layer['height'], 0],
[layer['Rahmen'][0] / 100, layer['Rahmen'][1] / 100, 1])]
Nachdem wir nun wissen, wie man mit einer Ebene umgeht, wenden wir sie auf alle Ebenen an. Der Grund für die Umkehrung ist, dass die überlappende Reihenfolge zwischen After Effects und Unity umgekehrt ist.
t_list = [([ps[0] - ps[1] * ps[3] + ps[2] * ps[3] / 2 for ps in zip(layer['Position'],layer['Ankerpunkt'],[layer['width'], layer['height'], 0], [layer['Rahmen'][0], layer['Rahmen'][1], 1])],
[layer['width'] * layer['Rahmen'][0] / 100, layer['height'] * layer['Rahmen'][1] / 100], layer['name']) for layer in root.values()]
t_list.reverse()
t_list
Nachdem wir die Koordinaten, die Breite und die Höhe für alle Ebenen kennen, geben wir den Bereich "Sofort" des Unity-Editors ein und generieren den C # -Code, um die Objekte in der Szene zu erstellen.
cs_str = '''{GameObject q = GameObject.CreatePrimitive(PrimitiveType.Quad);
q.name = "%s";
q.transform.position = new Vector3(%ff, %ff, %ff);
q.transform.localScale = new Vector3(%ff, %ff, 1.0f);
var m = (q.GetComponent<Renderer>().material = UnityEditor.AssetDatabase.LoadAssetAtPath<Material>("Assets/Textures/Background/_Materials/%s.mat"));
if (m != null) m.renderQueue = %d;
}'''
sss = '\n'.join([cs_str % (t[2].replace('.psd', ''),
t[0][0] / 1000, -t[0][1] / 1000, t[0][2] / 1000,
t[1][0] / 1000, t[1][1] / 1000, t[2].replace('.psd', ''),
3000 + i + start) for i, t in
enumerate(sorted(t_list, key=lambda t: int(t[0][2]), reverse=True)[start:start + lll])])
print(sss)
Durch Eingabe des Codes in den Bereich "Sofort" wurde die After Effects-Szene neu erstellt. Ich denke, es hat bis zu 50 Mal gedauert, aber ich denke, es ist ab dem zweiten Mal viel einfacher, weil der Designer mechanisch damit umgehen kann, selbst wenn er mit der After Effects-Szene spielt. Leider sagte der Designer: "Ich möchte nicht mehr mit so komplizierten und schwer zu bedienenden AE-Dateien spielen."
Gelegentlich codiere ich auch HTML, aber manchmal muss ich einen Teil wie eine Liste von Artikeln in einem Blog von Hand schreiben, in dem die Titelzeichenfolge usw. fast wiederholt oft vorkommt. Es ist die Rede davon, dass Sie CMS einfügen und mit einem statischen Website-Generator verwenden können, aber in den meisten Fällen müssen Sie der Veröffentlichung Vorrang vor dem HTML-Editor geben, wenn der sich wiederholende Teil insgesamt ein wenig ist Ich habe das Gefühl, dass es schneller ist, direkt zu schreiben (obwohl dies auch ein wichtiger Grund dafür ist, dass ich wenig Erfahrung mit HTML / CSS habe). Selbst in einem solchen Fall ist es mühsam und mühsam, dieselbe Zeichenkette an mehreren Stellen zu kopieren, und es ist nervenaufreibend, so dass der Programmierer das Gefühl hat, dass er sie überspringen möchte. Sobald ich es in Klammern schreibe und es gut angezeigt wird, werde ich eine Vorlage erstellen und sie ersetzen.
news_template=''' <article class="news-box">
<div class="news-photo-box"><img src="assets/image/news/###image_name###"></div>
<div class="news-date">###date_str###</div>
<div class="news-title">###title_str###</div>
<button class="news-more" alt="MORE"></button>
<div class="news-description news-description-hidden">
<button class="close-button"></button>
<button class="news-prev-button"></button>
<button class="news-next-button"></button>
<div class="news-description-inner">
<div class="news-description-pdt-box">
<div class="news-description-photo-box"><img src="assets/image/news/###image_name###"></div>
<div class="news-description-dt-box">
<div class="news-description-date">###date_str###</div>
<div class="news-description-title">###title_str###</div>
</div>
</div>
<div class="news-description-body">
###body_str###
</div>
</div>
</div>
</article>
'''
def make_news(date_str, title_str, body_str, image_name='default.png'):
return news_template \
.replace('###date_str###', date_str) \
.replace('###title_str###', title_str) \
.replace('###body_str###', body_str) \
.replace('###image_name###', image_name)
Jetzt können Sie definitiv HTML erstellen, indem Sie die erforderlichen Elemente eingeben. Es ist großartig, dies ohne Lernkosten tun zu können. Wenn ich gebeten werde, in Zukunft Neuigkeiten hinzuzufügen, denke ich, dass das Öffnen dieses Notizbuchs mich an alles erinnert, was ein guter Punkt in dem Sinne ist, dass es in Zukunft keine Schulden mehr hinterlassen wird, obwohl es nicht klar dokumentiert ist. Überlegen.
Außerdem,
Das Lesen und Konvertieren erfolgt meistens mit Jupyter Notebook, es sei denn, es kann mit einem einzigen Befehl ausgeführt werden.
Ich denke, es gibt viele Dinge, die Sie mit herkömmlichen Befehlszeilentools tun können, aber es ist mühsam, herauszufinden, wie die Tools verwendet werden, und über das Übergeben von Daten zwischen Tools nachzudenken, und es ist fast sicher, dass Datensätze erhalten bleiben und Sie von vorne beginnen müssen. Ich muss mir darüber keine Sorgen machen, deshalb verwende ich weiterhin Jupyter Notebook anstelle von Muscheln.
Denken Sie, Sie wurden getäuscht und versuchen Sie, das Jupyter-Notizbuch zu verwenden. Ich denke, dass es sehr gut für Leute geeignet ist, die von Projekt zu Projekt viel nicht standardisierte Arbeit haben.
Recommended Posts