我们经常要用py2exe将python脚本转换为单独的可执行文件,但是有一个麻烦就是要针对脚本写一个setup.py,在setup.py中指定一些信息,然后运行setup.py py2exe来生成执行文件。为避免每次都要写setup.py,本人编写了一个工具脚本pyfly.py,只要运行pyfly.py yourfile.py就能生成yourfile.exe。还可以为其指定其他参数,比如-i myicon.ico为生成的可执行文件添加图标;-p console指定生成控制台程序,-p windows指定生成windows程序;-c yes指定用upx压缩可执行文件以减小大小,-c no执行不压缩可执行文件;-d out_directory 指定生成的可执行文件的输出目录。(-c yes 选项 需要将upx.exe放置在系统的环境变量PATH所包含的目录中,或者将upx.exe的路径加入PATH中)

运行"pyfly.py pyfly.py", 就立即在当前目录下生成pyfly.exe,将pyfly.exe置于环境变量PATH中能找到的位置,然后在任意目录中就可为你的python脚本生成单文件的可执行程序了。

#-*- coding: utf8 -*-
import os,sys,re,time,uuid,subprocess,shutil,WConio

def printgoodnews(news):
    oldcolor
=WConio.gettextinfo()[4]
    WConio.textcolor(WConio.GREEN)
    
print news
    WConio.textcolor(oldcolor)

def printbadnews(news):
    oldcolor
=WConio.gettextinfo()[4]
    WConio.textcolor(WConio.RED)
    
print news
    WConio.textcolor(oldcolor)  

def delete_directory(path):
    
for root, subdirs,files in os.walk(path,topdown=False):
        
for file in files:
            os.unlink(os.path.join(root,file))
        
for subdir in subdirs:
            os.rmdir(os.path.join(root,subdir))
    os.rmdir(path)
            
usage
=r"""usage: pyfly script.py [-d out_directory] [-i iconfile] [-p console|windows] [-c yes|no]
('-c yes': call upx to compress exe)
e.g. : pyfly script.py -d c:\temp -i myicon.ico -p console 
     : pyfly script.py -d "c:\my directory"
"""

setuppy_console
="""\
from distutils.core import setup
import py2exe
setup(
    version = "",
    description = "",
    name = r"%s",
    options = {"py2exe": {"compressed": 1,
                          "optimize": 2,
                          "ascii": 0,
                          "bundle_files": 1}},
    zipfile = None,
    # targets to build
    console = [{"script": r"%s", "icon_resources": [(1, r"%s")]} ],
    )
"""

setuppy_noicon_console
="""\
from distutils.core import setup
import py2exe
setup(
    version = "",
    description = "",
    name = r"%s",
    options = {"py2exe": {"compressed": 1,
                          "optimize": 2,
                          "ascii": 0,
                          "bundle_files": 1}},
    zipfile = None,
    # targets to build
    console = [{"script": r"%s", } ],
    )
"""

setuppy_windows
="""\
from distutils.core import setup
import py2exe
setup(
    version = "",
    description = "",
    name = r"%s",
    options = {"py2exe": {"compressed": 1,
                          "optimize": 2,
                          "ascii": 0,
                          "bundle_files": 1}},
    zipfile = None,
    # targets to build
    windows = [{"script": r"%s", "icon_resources": [(1, r"%s")]} ],
    )
"""
setuppy_noicon_windows
="""\
from distutils.core import setup
import py2exe
setup(
    version = "",
    description = "",
    name = r"%s",
    options = {"py2exe": {"compressed": 1,
                          "optimize": 2,
                          "ascii": 0,
                          "bundle_files": 1}},
    zipfile = None,
    # targets to build
    windows = [{"script": r"%s", } ],
    )
"""

if __name__=="__main__"
    
    
if len(sys.argv)==1:
        printgoodnews(usage)
        sys.exit(
-1)
            
    script
=sys.argv[1]
    
    platform
='console'
    out_directory
=os.getcwd()
    iconfile
=""
    upx
="no"
    
if script[-3:].lower()!=".py" or not os.path.exists(script):
        printbadnews(
"%s is not a valid python source file or not exists!")
        printgoodnews(usage)
        sys.exit(
-1)


    
try:      
        
if len(sys.argv)>2 and len(sys.argv)<=8 and len(sys.argv) % 2==0:  
            options
=[item.lower() for item in sys.argv[2::2]]
            
for option in options:
                
if option not in ['-p','-d','-i','-c']:
                    
raise Exception(r'invalid option: %s!' % option)            
            
if '-p' in options:
                platform
=sys.argv[sys.argv.index('-p')+1].lower()
                
if platform not in ['console','windows']:
                    
raise Exception(r"%s is not a valid platform, you should use 'console' or 'windows'!" % platform)
            
if '-d' in options:
                out_directory
=sys.argv[sys.argv.index('-d')+1]
                
if not os.path.exists(os.path.abspath(out_directory)):
                    
raise Exception(r"%s is not a valid directory!" % out_directory)
            
if '-i' in options:
                iconfile
=sys.argv[sys.argv.index('-i')+1]
                
if not os.path.exists(os.path.abspath(iconfile)) or iconfile[-4:].lower()!='.ico':
                    
raise Exception(r"%s is not a valid icon file name or not exists!" % iconfile)
            
if '-c' in options:
                upx
=sys.argv[sys.argv.index('-c')+1].lower()
                
if upx not in ['yes','no']:
                    
raise Exception(r"%s option must be set to 'yes' or 'no'!" % "-c")
        
elif len(sys.argv)==2:
            
pass
        
else:
            
raise Exception('Invalid counts of arguments!')
    
except Exception,e:
        printbadnews(str(e))
        printgoodnews(usage)
        sys.exit(
-1)
            
     
    
try:
        tempdir
=os.environ['temp']

        
#create setup.py in temp directory
        setupfile=os.path.join(tempdir,str(uuid.uuid1())+".py")
        
while os.path.exists(setupfile):
            setupfile
=os.path.join(tempdir,str(uuid.uuid1())+".py")
        g
=open(setupfile,'wb')
        
if iconfile!="":
            g.write(eval(
'setuppy_%s' % platform) % (os.path.basename(script),script,iconfile))
        
else:
            g.write(eval(
'setuppy_noicon_%s' % platform) % (os.path.basename(script),script)) 
        g.close()  
        
del g

        
if " " in out_directory:
            out_directory
='"'+out_directory+'"'
                          
        cmd
=r'python "%s" py2exe -O2 -d %s' %(setupfile,out_directory)
        
#print cmd
        if subprocess.call(cmd)==0:
            
#delete temporary file and 'build' directory 
            os.unlink(setupfile)    
            cwd
=os.getcwd()
            build
=os.path.join(cwd,'build')
            bdist_win32
=os.path.join(build,'bdist.win32'
            delete_directory(bdist_win32)
            
#if build is a blank directory, delete it; otherwise keep it.
            i=0
            
for root,subdirs,files in os.walk(build,topdown=True):
                
if subdirs!=[] or files!=[]:
                    i
+=1
                    
break    
            
if i==0:
                delete_directory(build)            
            
# compress exe
            if upx=='yes':
                subprocess.call(
'upx -9 -v "%s.exe"' % os.path.join(out_directory,os.path.basename(script)[0:-3]))  
       
    
except Exception,e:
        printbadnews(str(e))



posted on 2007-11-01 10:15  玛瑙河  阅读(3290)  评论(0)    收藏  举报