[PYTHON] Ersetzen Sie alle Flags, die in maya.cmds mit Kurznamen geschrieben wurden, durch Langnamen

Dieser Artikel ist ein Artikel vom 20. Dezember des Maya-Python-Adventskalenders 2016.

Einführung

In maya.cmds können Sie das Flag, das an den Befehl übergeben werden soll, auf zwei Arten schreiben: ** Kurznamen-Notation ** und ** Langnamen-Notation **. Wenn Sie beispielsweise den Befehl maya.cmds.optionMenu verwenden, um Prozesse mit derselben Bedeutung in Kurz- und Langnamen zu schreiben, sieht dies folgendermaßen aus.

#Kurzname Notation
cmds.optionMenu(name, en=True, l="top_node:",
                vis=True, ann=u"Wählen Sie den obersten Knoten aus", w=200,
                cc=partial(self.change_topnode, name))

#Langname Notation
cmds.optionMenu(name, enable=True, label="top_node:",
                visible=True, annotation=u"Wählen Sie den obersten Knoten aus", width=200,
                changeCommand=partial(self.change_topnode, name))

Die Kurznamen-Notation macht den Code kompakter, daher ist er möglicherweise besser für diejenigen, die daran gewöhnt sind. Für maya.cmds-Anfänger wie mich wird jedoch jedes Mal, wenn beim Erben oder Überprüfen von Code, der von einer anderen Person geschrieben wurde, ein Kurznamen-Flag angezeigt wird, [Autodesks Maya Python-Befehlsreferenz](http: // help) .autodesk.com / cloudhelp / 2016 / JPN / Maya-Tech-Docs / CommandsPython / index.html) ist ineffizient.

Daher werden wir dieses Mal ein Skript erstellen, das das Kurznamen-Notationsflag sofort durch das Langnamen-Notationsflag ersetzt.

Umgebung

Der Betrieb des Programms wurde in der folgenden Umgebung bestätigt.

Vorbereitung

Es ist nur ein externes Modul namens astor erforderlich. Installieren Sie es daher mit pip.

pip install astor

Verwenden Sie AST (Abstract Syntax Tree)

AST (Abstract Syntax Tree) wird verwendet, um die Parameternamen zu analysieren und zu ersetzen, die beim Aufrufen der Funktion maya.cmds verwendet werden. Mit dem im Python-Standard enthaltenen ast-Modul können Sie einen AST erhalten, indem Sie einfach den Code analysieren, den Sie analysieren möchten.

import ast


if __name__ == '__main__':

    example = """def fake(x):
        import maya.cmds as cmds
        cmds.optionMenu(name, q=True, v=True)
        return 0
    """

    tree = ast.parse(example)
    print ast.dump(tree)

Wenn das obige Programm ausgeführt wird, wird das folgende Ergebnis ausgegeben.

Module(body=[FunctionDef(name='fake', args=arguments(args=[Name(id='x', ctx=Param())], 
vararg=None, kwarg=None, defaults=[]), body=[Import(names=[alias(name='maya.cmds', 
asname='cmds')]), Expr(value=Call(func=Attribute(value=Name(id='cmds', ctx=Load()), 
attr='optionMenu', ctx=Load()), args=[Name(id='name', ctx=Load())], 
keywords=[keyword(arg='q', value=Name(id='True', ctx=Load())), keyword(arg='v', 
value=Name(id='True', ctx=Load()))], starargs=None, kwargs=None)), 
Return(value=Num(n=0))], decorator_list=[])])

Es ist ein bisschen lang und schwer zu lesen, aber hier

Es ist wichtig, dass Sie Informationen über die Region erhalten. Mit anderen Worten, Sie können sehen, welcher Befehl in maya.cmds mit welchem Flag-Argument ausgeführt wird.

Führen Sie den Befehl help () mit mayapy aus

Nachdem wir nun wissen, dass wir mit AST herausfinden können, ob die Kurznamen-Notation im Code verwendet wird, besteht der nächste Schritt darin, die Entsprechungstabelle zwischen der Kurznamen-Notation und der Langnamen-Notation in jeder maya.cmds abzurufen. Wenn Sie den Befehlsnamen an maya.cmds.help () übergeben, werden die Kurznamen- und Langnamen-Notation wie unten gezeigt zurückgegeben.

import maya.cmds
print(maya.cmds.help("optionMenu"))

-----------------------------------------------------
einpacken: optionMenu [flags] [String]
Flags:
   -e -edit
   -q -query
 -acc -alwaysCallChangeCommand 
 -ann -annotation               String
 -bgc -backgroundColor          Float Float Float
  -cc -changeCommand            Script
...(Kürzung)

Generieren Sie dynamisch ein Diktat mit der Kurznamen-Notation als Schlüssel und der Langnamen-Notation als Wert unter Verwendung regulärer Ausdrücke.

help_regex.py


method_name_dict = {}

help_messages = cmds.help(method_name)
method_name_dict[method_name] = {}

for line in help_messages.split(os.linesep):
    arg_names = re.search(r"-([a-zA-Z0-9]+) -([a-zA-Z0-9]+)", line)
    if arg_names:
        method_name_dict[method_name][arg_names.group(1)] = arg_names.group(2)

Sie können ein Diktierobjekt wie dieses erstellen

[('optionMenu', {u'en': u'enable', u'cc': u'changeCommand', u'm': u'manage', u'ann': u'annotation',  ...(Kürzung)

Der Befehl maya.cmds.help () muss jedoch in der Python-Ausführungsumgebung von maya ausgeführt werden. (Normalerweise wird mit Python aaa.py nichts zurückgegeben.)

Für Mac /Applications/Autodesk/maya2015/Maya.app/Contents/bin/mayapy Für Windows C:\Program Files\Autodesk\Maya2015\bin\mayapy.exe

Es gibt Mayapy. Wenn Sie also ein Python-Programm damit ausführen, erhalten Sie das Ergebnis des Befehls help (). /Applications/Autodesk/maya2015/Maya.app/Contents/bin/mayapy aaa.py

Jetzt können Sie den Kurznamen durch den Langnamen ersetzen.

Ersetzen Sie Knoten durch ast.NodeTransformer

Verwenden Sie NodeTransformer, um jedes Element des AST zu überprüfen, zu ersetzen oder zu löschen. Wenn Sie beispielsweise wie folgt etwas mit dem Funktionsaufrufknoten (Call) tun möchten, definieren Sie die Funktion visit_Call (self, node) und schreiben Sie den Prozess.

class MayaPythonShort2LongNameNodeTransformer(ast.NodeTransformer):
    def visit_Call(self, node):
        #Ich werde den Austauschprozess hier schreiben

Nachdem Sie den Flag-Namen durch NodeTransformer ersetzt haben, kehren Sie schließlich mit astor.to_source () zum Python-Code zurück.

print(astor.to_source(tree).decode("unicode-escape"))

Kurzname-> Langname-Ersetzungsskript

Der folgende Code ist eine angemessene Zusammenfassung der obigen Verarbeitung.

maya_cmds_name_converter.py


# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
import os
import re
import ast
import astor
import maya.standalone
import maya.cmds as cmds


class MayaPythonShort2LongNameNodeTransformer(ast.NodeTransformer):
    def __init__(self):
        self.method_name_dict = {}

    @staticmethod
    def is_maya_cmds_func(node):
        return hasattr(node, "func") and hasattr(node.func, "value") and hasattr(node.func.value, "id") and \
            node.func.value.id == "cmds"

    def visit_Call(self, node):

        if self.is_maya_cmds_func(node):
            method_name = node.func.attr

            if not self.method_name_dict.get(method_name):
                # short_Name und lang_Erstellen Sie ein entsprechendes Diktat für den Namen
                try:
                    help_messages = cmds.help(method_name)
                except RuntimeError:
                    # print(u"help()Ist ein nicht unterstützter Befehl: " + method_name)
                    return node

                self.method_name_dict[method_name] = {}
                for line in help_messages.split(os.linesep):
                    arg_names = re.search(r"-([a-zA-Z0-9]+) -([a-zA-Z0-9]+)", line)
                    if arg_names:
                        self.method_name_dict[method_name][arg_names.group(1)] = arg_names.group(2)

            for keyword in node.keywords:
                if keyword.arg in {"q", "e", "c", "m"}:
                    #Ignorieren, wenn Basisflag
                    continue

                long_name = self.method_name_dict[method_name].get(keyword.arg)
                if long_name:
                    if long_name == "import":
                        #In diesem Fall wird es seltsam wie Python
                        continue

                    # print(keyword.arg + u"Zu" + long_name + u"Konvertieren zu")
                    keyword.arg = long_name

        return node


if __name__ == '__main__':
    maya.standalone.initialize(name='python')

    #Beispielcode zum Testen
    example = """def fake(x):
        import maya.cmds as cmds
        cmds.optionMenu(name, en=True, l="top_node:",
                vis=True, ann=u"Wählen Sie den obersten Knoten aus", w=200,
                cc=partial(self.change_topnode, name))
        return top_node
    """

    tree = ast.parse(example)
    tree = MayaPythonShort2LongNameNodeTransformer().visit(tree)

    # after convert python code
    print(astor.to_source(tree).decode("unicode-escape"))

    if float(cmds.about(v=True)) >= 2016:
        maya.standalone.uninitialize()

Wenn dieses Programm ausgeführt wird, wird der Befehl des zu Beginn eingeführten Kurznamen-Notationsflags durch die Langnamen-Notation und -Ausgabe ersetzt.

Vor dem Austausch


def fake(x):
        import maya.cmds as cmds
        cmds.optionMenu(name, en=True, l="top_node:",
                vis=True, ann=u"Wählen Sie den obersten Knoten aus", w=200,
                cc=partial(self.change_topnode, name))
        return top_node

Nach dem Austausch


def fake(x):
    import maya.cmds as cmds
    cmds.optionMenu(name, enable=True, label='top_node:', visible=True, annotation=u'Wählen Sie den obersten Knoten aus', width=200, changeCommand=partial(self.change_topnode, name))
    return top_node

Vorsichtsmaßnahmen / Einschränkungen

Es schien zu funktionieren, aber nachdem ast.parse den Python-Code, wenn ich ihn mit astor.to_source () wieder in den Python-Code konvertiere, verliere ich viele Formatierungsinformationen.

--u "" "Dies ist eine Dokumentationszeichenfolge" "" ist alles u \ Dies ist eine Dokumentationszeichenfolge \

Nachdem ich Kurznamen-> Langnamen ersetzt habe, bereinige ich sie separat mit AutoFormatter / Löschen von Warnungen / Ersetzen durch PyCharm. ..

Zusammenfassung

Wenn Sie sich daran gewöhnt haben, ist die Kurznamen-Notation möglicherweise einfacher zu schreiben und zu lesen, aber ich kann mich immer noch nicht an die große Anzahl von Flags erinnern, die in maya.cmds enthalten sind.

Wie erwartet ist l Label, v ist Wert usw., daher halte ich es für eine gute Idee, die Regel des Flaggennamens entsprechend der Kompetenzstufe des am Code beteiligten Teams zu bestimmen. Wenn es sich um ein Flag handelt, das anscheinend nur selten verwendet wird, können Sie die Bedeutung anhand des langen Namens verstehen. Wenn es sich jedoch um einen kurzen Namen handelt, wird definitiv etwas als Befehlsreferenz gesendet. Seien Sie also vorsichtig.

bsp -> beforeShowPopup npm -> numberOfPopupMenus vcc -> visibleChangeCommand Und.

Recommended Posts

Ersetzen Sie alle Flags, die in maya.cmds mit Kurznamen geschrieben wurden, durch Langnamen
Ersetzen Sie alles auf einmal durch sed
Stresstest mit Locust in Python geschrieben
Gacha in Python-Rarity geschrieben mit Bonus bestätigt
Ersetzen Sie Nicht-ASCII durch reguläre Ausdrücke in Python
Ersetzen Sie Spaltennamen / -werte durch Pandas-Datenrahmen