2016-01-20 153 views
0

這是來自另一個堆棧線程的建議,我終於回到了。這是關於如何將工具嵌入到maya文件中的討論的一部分。Maya Python - 將zip文件嵌入到maya文件中?

你可以把整個東西寫成一個python包,壓縮它,然後將zip文件的二進制內容填充到fileInfo中。當您需要編碼時,請在用戶的$ MAYA_APP_DIR中查找;如果沒有拉鍊,寫的fileInfo的內容磁盤作爲一個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文件中?

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

更新: 瑪雅人不喜歡寫文件爲UTF-8編碼的直接讀取zip文件。我發現了各種方法,使它成爲可寫入的可接受字符串,但解碼迴文件似乎不起作用。我現在看到Theodox的建議是將它寫入二進制文件並將其放入fileInfo節點。

如何編碼,存儲然後解碼以後寫入文件?

如果我要轉換使用實例二進制:

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

我需要什麼樣的代碼把這一回原始UTF-8 zip文件的信息?

回答

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-safe表示的方法都可以正常工作,只要您使用可逆方法:需要注意的潛在問題是數據塊中的一個字符,它看起來像maya報價 - 一個開放的報價int他fileInfo將麻煩在MA文件。

本示例使用YAML執行任意鍵值對,但該部分與存儲二進制文件無關。我已經使用這種技術相當大的數據(多達640K,如果我記得),但我不知道它在什麼你可以在Maya

藏匿條款上限
+0

呸。比我所有的要容易得多。謝謝! –

0

找到了答案。偉大的腳本堆棧溢出。我必須編碼爲'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')) 

,這似乎工作..到目前爲止..

0

想我會發布最終產品適合任何想要採用這種方法的人。我試圖做一些腐敗檢查,以便在機器之間不傳遞錯誤的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)