【问题标题】:Maya Python - Embed zip file into maya file?Maya Python - 将 zip 文件嵌入到 Maya 文件中?
【发布时间】:2016-04-26 21:58:47
【问题描述】:

这是来自另一个堆栈线程的建议,我终于回来了。这是关于如何将工具嵌入到 Maya 文件中的讨论的一部分。

你可以把整个东西写成一个python包,压缩它,然后把zip文件的二进制内容塞进一个fileInfo中。需要编码时,在用户的$MAYA_APP_DIR中查找;如果没有 zip,则将 fileInfo 的内容作为 zip 写入磁盘,然后将 zip 插入 sys.path

来源讨论是: python copy scripts into scriptMaya Python Create and Use Zipped Package?

到目前为止,编程进展顺利,但我想我遇到了障碍。当我尝试这样做时:

with open("..directory/myZip.zip","rb") as file:
    cmds.fileInfo("myZip", file.read())

..然后我..

print cmds.fileInfo("myZip",q=1)

我明白了

[u'PK\003\004\024']

当将 zip 文件作为文本文档读取时,这是对第一行乱码的错误翻译。

如何将我的 zip 文件作为二进制文件嵌入到我的 maya 文件中?

=====================

更新: Maya 不喜欢将文件写入为直接读取 utf-8 编码的 zip 文件。我发现了各种将其变成可以写入的可接受字符串的方法,但是解码回文件似乎不起作用。我现在看到 Theodox 的建议是将其写入二进制文件并将其放入 fileInfo 节点中。

如何编码、存储然后解码以便稍后写入文件?

如果我要使用例如转换为二进制:

' '.join(format(ord(x), 'b') for x in line)

我需要什么代码才能将其转回原始的 utf-8 zip 信息?

【问题讨论】:

    标签: python zip embed maya


    【解决方案1】:

    我想我会为任何想要采用这种方法的人发布最终产品。我尝试进行一些损坏检查,以免在机器之间传递错误的 zip。这就是所有检查哈希的用途。

    def writeTimeFull(tl):
        import TimeFull
        #reload(TimeFull)
        with open(TimeFull.__file__.replace(".pyc",".py"),"r") as file:
            cmds.scriptNode( tl.scriptConnection[1][0], e=1, bs=file.read() )
        cmds.expression("spark_timeliner_activator",
                        e=1,s='if (Spark_Timeliner.ShowTimeliner == 1)\n'
                              '{\n'
                              '\tsetAttr Spark_Timeliner.ShowTimeliner 0;\n'
                              '\tpython \"Timeliner.InitTimeliner()\";\n'
                              '}',
                        o="Spark_Timeliner",ae=1,uc=all)
    
    def checkHash(zipPath,hash1,hash2,hash3):
        check = False
        hashes = [hash1,hash2,hash3]
        for ii, hash in enumerate(hashes):
            if hash == hashes[(ii+1)%3]:
                hashes[(ii+2)%3] = hashes[ii]
                check = True
        if check:
            if md5(zipPath) == hashes[0]:
                return [zipPath,hashes[0],hashes[1],hashes[2]]
        else:
            cmds.warning("Hash checks and/or zip are corrupted. Attain toolbox_fix.zip, put it in scripts folder and restart.")
            return []
    
    #this writes the zip file to the local users space
    def saveOutZip(filename):
        if os.path.isfile(filename):
            if not os.path.isfile(filename.replace('_pkg','_'+__version__)):
                os.rename(filename,filename.replace('_pkg','_'+__version__))
        with open(filename,"w") as zipFile:
            zipInfo = cmds.fileInfo("zipInfo1",q=1)[0]
            zipHash_1 = cmds.fileInfo("zipHash1",q=1)[0]
            zipHash_2 = cmds.fileInfo("zipHash2",q=1)[0]
            zipHash_3 = cmds.fileInfo("zipHash3",q=1)[0]
            zipFile.write( base64.b64decode(zipInfo) )
            if checkHash(filename,zipHash_1,zipHash_2,zipHash_3):
                cmds.fileInfo("zipInfo2",zipInfo)
                return filename
        with open(filename,"w") as zipFile:
            zipInfo = cmds.fileInfo("zipInfo2",q=1)[0]
            zipHash_1 = cmds.fileInfo("zipHash1",q=1)[0]
            zipHash_2 = cmds.fileInfo("zipHash2",q=1)[0]
            zipHash_3 = cmds.fileInfo("zipHash3",q=1)[0]
            zipFile.write( base64.b64decode(zipInfo) )
            if checkHash(filename,zipHash_1,zipHash_2,zipHash_3):
                cmds.fileInfo("zipInfo1",zipInfo)
                return filename
        return False
    
    #this writes the local zip to this file
    def loadInZip(filename):
        zipResults = []
        for ii in range(0,10):
            with open(filename,"r") as theRead:
                zipResults.append([base64.b64encode(theRead.read())]+checkHash(filename,md5(filename),md5(filename),md5(filename)))
            if ii>0 and zipResults[ii]==zipResults[ii-1]:
                cmds.fileInfo("zipInfo1",zipResults[ii][0])
                cmds.fileInfo("zipInfo2",zipResults[ii-1][0])
                cmds.fileInfo("zipHash1",zipResults[ii][2])
                cmds.fileInfo("zipHash2",zipResults[ii][3])
                cmds.fileInfo("zipHash3",zipResults[ii][4])
                return True
    
    #file check
    #http://stackoverflow.com/questions/3431825/generating-a-md5-checksum-of-a-file
    def md5(fname):
        import hashlib
        hash = hashlib.md5()
        with open(fname, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash.update(chunk)
        return hash.hexdigest()
    
    filename = path+'/toolbox_pkg.zip'
    zipPaths = [path+'/toolbox_update.zip',
                path+'/toolbox_fix.zip',
                path+'/toolbox_'+__version__+'.zip',
                filename]
    zipPaths_exist = [os.path.isfile(zipPath) for zipPath in zipPaths ]
    
    if any(zipPaths_exist[:2]):
        if zipPaths_exist[0]:
            cmds.warning('Timeliner update present. Forcing file to update version')
            if zipPaths_exist[2]:
                os.remove(zipPaths[3])
            elif os.path.isfile(zipPaths[3]):
                os.rename(zipPaths[3], zipPaths[2])
            os.rename(zipPaths[0],zipPaths[3])
            if zipPaths_exist[1]:
                os.remove(zipPaths[1])
        else:
            cmds.warning('Timeliner fix present. Replacing file to the fix version.')
            if os.path.isfile(zipPaths[3]):
                os.remove(zipPaths[3])
            os.rename(zipPaths[1],zipPaths[3])
        loadInZip(filename)
    
    if not cmds.fileInfo("zipInfo1",q=1) and not cmds.fileInfo("zipInfo2",q=1):
        loadInZip(filename)
    
    if not os.path.isfile(filename):
        saveOutZip(filename)
    
    sys.path.append(filename)
    import Timeliner
    Timeliner.InitTimeliner(theVers=__version__)
    
    if not any(zipPaths[:2]):
        if __version__ > Timeliner.__version__:
            cmds.warning('Saving out newer version of timeliner to local machine. Restart Maya to access latest version.')
            saveOutZip(filename)
        elif __version__ < Timeliner.__version__:
            cmds.warning('Timeliner on machine is newer than file version. Saving machine version over timeliner in file.')
            loadInZip(filename)
            __version__ = Timeliner.__version__
    
    if __name__ != "__main__":
        tl = getTimeliner()
        writeTimeFull(tl)
    

    【讨论】:

      【解决方案2】:

      你可以在这里找到相关代码:

      http://tech-artists.org/forum/showthread.php?4161-Maya-API-Singleton-Nodes&highlight=mayapersist

      相关位是

        import base64
        encoded = base64.b64encode(value)
        decoded = base64.b64decode(encoded)
      

      基本上是相同的想法,除了使用 base64 模块而不是 binascii。只要您使用可逆方法,任何将任意字符流转换为 ascii 安全表示的方法都可以正常工作:您需要注意的潜在问题是数据块中的一个字符,看起来像一个关闭的 Maya quote - fileInfo 中的开放式引用会在 MA 文件中变得混乱。

      此示例使用 YAML 来执行任意键值对,但该部分与存储二进制内容无关。我已经将这种技术用于相当大的数据(如果我记得最多可达 640k),但我不知道它在 Maya 中存储的内容是否有上限

      【讨论】:

      • 呸。比我所拥有的要容易得多。谢谢!
      【解决方案3】:

      找到了答案。堆栈溢出的好脚本。我必须编码为“string_escape”,这是我在试图弄清楚整个字符情况时发现的。但无论如何,您打开 zip,编码为“string_escape”,将其写入 fileInfo,然后在获取将其写回 zip 之前,将其解码。

      Convert binary to ASCII and vice versa

      import maya.cmds as cmds
      import binascii
      
      def text_to_bits(text, encoding='utf-8', errors='surrogatepass'):
          bits = bin(int(binascii.hexlify(text.encode(encoding, errors)), 16))[2:]
          return bits.zfill(8 * ((len(bits) + 7) // 8))
      
      def text_from_bits(bits, encoding='utf-8', errors='surrogatepass'):
          n = int(bits, 2)
          return int2bytes(n).decode(encoding, errors)
      
      def int2bytes(i):
          hex_string = '%x' % i
          n = len(hex_string)
          return binascii.unhexlify(hex_string.zfill(n + (n & 1)))
      

      然后你就可以了

      with open("..\maya\scripts/test.zip","rb") as thing:
          texty = text_to_bits(thing.read().encode('string_escape'))
          cmds.fileInfo("binaryZip",texty)
      

      ...稍后

      with open("..\maya\scripts/test_2.zip","wb") as thing:
          texty = cmds.fileInfo("binaryZip",q=1)
          thing.write( text_from_bits( texty ).decode('string_escape') )
      

      这似乎有效..到目前为止..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-09
        • 2018-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-19
        • 2012-07-01
        相关资源
        最近更新 更多