Python resource packaging script

Keywords: Python Windows

  • Using Python to implement calling system api to execute TexturePacker instructions to map resources
  • Using zipfile Library in Python to make zip package operation on the completed graph
  • Python is also on sale now. To do this, first of all, I need to be familiar with python's functions related to file manipulation.
  • Environment: Windows 7 | Python 2.7.5 | TexturePacker 3.0.9

Using scripts to execute TexturePacker instructions to map image resources

Schematic map of resource distribution

  • Operations on resources in all subfolders of res folder
  • For example, path:. / dir/res/1_001/(3-5 maps)

Block diagram code

  • TexturePacker is required to install and configure environment variables. Enter TexturePacker in the terminal to detect
  • Recommendations on TexturePacker Directives This article

Code:

import os,os.path,sys
# Pack
class PackerHelper(object):
    def __init__(self,inputDir,outputDir):
        super(PackerHelper, self).__init__()
    # TexturePacker directive
        self.sCmd_tp = 'TexturePacker'
    # Receiving parameter resource path
        self.inputDir   = inputDir  
    # Receiving parameter output path         
    self.outputDir  = outputDir
        print u"\n******************"
        print u"The Resource Path of the Required Composite Map   -> %s"%self.inputDir
        print u"The resource output path of the desired composite graph -> %s"%self.outputDir
        print u"******************\n"

    # ----------
    # Packaging resources
    def packer(self):
        resDirList = os.listdir(self.inputDir)
        print u"existence%d Four folders to be combined "%len(resDirList)
        # Traverse folders (i.e. folders 1_001-1_024)
        for n in range(len(resDirList)):
            # Stitching new save paths
            outPath = os.path.join(self.outputDir,resDirList[n])
            # Stitching new input paths
            inputPath = os.path.join(self.inputDir,resDirList[n])
            # Get the file name in each folder
            fimeNameList = os.listdir(inputPath)
                # Instruction copy
            tp_cmd = self.sCmd_tp
            # Splicing resource paths (path/fileName paht/fileName....)
            allImage = ""
            for im in range(len(fimeNameList)):
                allImage = allImage + " " + inputPath + os.sep + fimeNameList[im]
            # Splicing and packaging instructions (here only for hash map synthesis operations, other processing is not required, instructions can be referred to http://blog.csdn.net/lovehappy108/article/details/51462831)
            tp_cmd = tp_cmd + " " + allImage +\
                    " --data " + outPath + os.sep + resDirList[n] + ".plist"\
                    " --sheet " + outPath + os.sep + resDirList[n] + ".png"\
                    " --format " + "cocos2d"
                    # " --border-padding 0" \
                    # " --trim-mode Trim" \
                    # " --basic-sort-by Name" \
                    # " --basic-order Ascending" \
                    # ....
            # Call system api to execute TexturePacker instructions
            os.system(tp_cmd)
        print u"Combined graph completion!"

if __name__ =='__main__':
    inputDir        = 'C:\\Users\\Administrator\\Desktop\\dir\\res\\'         # Resource path
    inputDir_pack   = 'C:\\Users\\Administrator\\Desktop\\dir\\outDir_pack'   # Derived graph paths

    # Packing hash map resources first
    sPackerHelper = PackerHelper(inputDir,inputDir_pack)
    sPackerHelper.packer()

Result diagram

  • Next is the zip operation of the folder (word folder in outDir_pack) after completing the drawing.

Using zipfile Library in Python to zip folders

  • The purpose of zip folders is to provide download and decompression operations on the game client. Here are some points:
    • zip package size preservation
    • zip package name preservation
    • Number of resources saved in zip packages
    • The md5 of zip package is saved (the picture resources are modified later, and need to be downloaded again to determine whether the zip package has changed)
  • According to these points mentioned above, the corresponding configuration files need to be generated to save in the packaging process.
  • Compression is done here first, and the next step of the configuration file is to produce.

Packing code

import os,os.path,sys
import zipfile  # zip operation
import hashlib  # md5 generation

# compress
class ZipHelper(object):
    def __init__(self,desPath,outpath):
        super(ZipHelper, self).__init__()
        # Path to Pack
        self.desPath = desPath 
        # Output Path of Packing Completion
        self.outpath = outpath
        print u"\n******************"
        print u"The resource path to be packaged   -> %s"%self.desPath
        print u"The resource output path to be packaged -> %s"%self.outpath
        print u"******************\n"
        # Check the existence of zip file save path
        if not os.path.exists(self.outpath):
            print u"Compressed Packet Output Folder  ->%s Non-existent!!"%self.outpath
            os.makedirs(self.outpath)
            print u"Compressed Packet Output File Creation Completed ->%s"%self.outpath

        # Collection of folders to be compressed
        self.zipDirs = []

    # Get all files under a folder
    def getDirFiles(self,dirPath):
        # Containers for loading files (['C: Users Administrator Desktop dir outDir_pack 1_001 plist','C: Users Administrator\ Desktop Dir outpack 1_001 png')
        fileList = []
        # If it's a file, add it directly to the container.
        if os.path.isfile(dirPath):
            fileList.append(dirPath) 
        else :
            # Traversing directories instead of files
            for root, dirs, files in os.walk(dirPath):
                for name in files:
                    # Add the path and file name stitching to the container
                    fileList.append(os.path.join(root, name))
        return fileList

    def run(self):
        # Get all folder names under the directory (all word folder names under dir/outDir_pack ['1_001','1_002',...'1_024'])
        rootList = os.listdir(self.desPath)
        # Loop these folders for action
        for i in range(0,len(rootList)):
            # Get the name of each folder (1_001...)
            dirName = rootList[i]
            # Splicing folder path (resource path + subfile name [C: Users Administrator Desktop dir outDir_pack 1_001, C: Users Administrator Desktop dir outDir_pack 1_002])
            filepath = os.path.join(self.desPath,rootList[i])
            # Determine whether the path is a file?
            if not os.path.isfile(filepath):
                # If it's not a file, get all the resources in the folder (currently. plst and a png map, not a composite map in front of it)
                files = self.getDirFiles(filepath)
                # Data for assembling each zip package (name, zip package name [path + file name + suffix], resource to be packaged [plist,png])
                task = {'name':('name="%s"'%dirName),'des' : self.outpath+dirName+".zip",'fileList' : files}
                # The zip data to be packaged is stored in the container for packaging operations
                self.zipDirs.append(task)

        print u"zip Number:%d" % len(self.zipDirs)

        # Traverse the container data to be packaged
        for task in self.zipDirs:
            # Remove zip name (path + file name + suffix)
            zipFileName = task['des']
            # Remove the resource to enter the zip package (plist+png)
            fileList = task['fileList']
            # Call the zipfile library for packaging (param01:zip name, param02: create a new zip or overwrite an existing zip,param03: compression)
            zf = zipfile.ZipFile(zipFileName, "w", zipfile.ZIP_STORED)
            # Loop traversal pushes resources (plist, and png) into zip packages
            for tar in fileList:
                arcname = tar[len(self.desPath):]
                # Add file resources to zip packages and carry paths (used when decompressing, file resources [plist,png])
                zf.write(tar,"res\\normal\\atlas_image\\"+arcname)
            zf.close()
            print u"Compressing...  -> %s" % (task['des'])
            #Each data in the self.zipDirs container is followed by two additional fields md5\size
            # Add a field md5 after task
            task['md5']  = 'md5="%s"'%self.getFileMD5New(zipFileName)
            # Add a field size record byte after task
            task['size'] = 'size="%s"'%os.path.getsize(zipFileName)
        print u"Compression completed!"

    # MD5 Code for Generating zip Files
    def getFileMD5New(self,filePath):
        # zip package
        zipInfo = zipfile.ZipFile(filePath,'r')
        # MD5 operation
        md5 = hashlib.md5()
        # Get each zip file to update the production md5
        for oneFile in zipInfo.infolist():
            text = zipInfo.read(oneFile)
            md5.update(text)
        zipInfo.close()
        return md5.hexdigest()

if __name__ =='__main__':
    inputDir_pack   = 'C:\\Users\\Administrator\\Desktop\\dir\\outDir_pack'   # Derived graph paths
    inputDir_zip    = 'C:\\Users\\Administrator\\Desktop\\dir\\outDir_zip\\'  # Exported zip package path

    # Post-Compressed Zip Packet
    sZipHelper = ZipHelper(inputDir_pack,inputDir_zip)
    # Start processing
    sZipHelper.run()

Result diagram

  • Next, the production configuration file is processed.

Production Profile

  • The data needed to be saved (name, size, number of resources, md5) to generate the configuration file is described above, and other information besides the number of resources is saved in the container.
  • The number of resources you need to know here is not the number after the composition (plist and png), but the number before the composition, so you need to add a container in the PackerHelper class to store the number of resources in each folder.
  • Then, in the ZipHelper class, you call the number of containers saved in PackerHelper to get the number of resources per folder, which you can see in the source code file below. Only the functions written to the configuration file are listed here.
  • Add a method start_create_Info_file() to the ZipHelper class to write data to the configuration file, because here I debug on the lua side, so these fields are saved as lua tables.

Create and write configuration file code

# Start creating version files
def start_create_Info_file(self):
    # Create version files
    pFile = open(os.path.join(self.outpath, "config.txt"),'w')
    # Write its starting data
    pFile.write("local atlas_config = {\n")
    # Traversing data containers
    for task in self.zipDirs:
        name  = task['name']    # file name
        count = task['count']   # Number of documents
        md5   = task['md5']     # File MD5
        size  = task['size']    # File bytes (size)
        # Write data
        pFile.write("{%s,%s,%s,%s},\n" % (name,count,size,md5))
    # Write end data
    pFile.write("}\nreturn atlas_config")
    pFile.close()

Result diagram

Resource downloading

Click here to download CSDN

  • Each small function in this script needs to come up with a single practice to see its usefulness. Call these small functions chunks, and when you understand them, merge them together. I'm doing the same thing, like os.path.join | os.listdir | for loops... Wait.

Posted by dewknight on Wed, 29 May 2019 10:39:13 -0700