美文网首页PythonLinuxpython
手把手 | 教你打包Python脚本并用TBtools完成程序界

手把手 | 教你打包Python脚本并用TBtools完成程序界

作者: 生信石头 | 来源:发表于2022-11-27 12:23 被阅读0次

    导语

    前述,师弟 Chuhao Li 用 Python 开发了第一个 TBtools CLI Program Wrapper Creator 插件。插件的实用性和制作的精细程度出乎意料。感慨之余,我邀请他给大伙分享一下制作经验(因为我完全不懂 Python,而我知道 Python 是现在绝大多数朋友最喜欢用的语言)。收到推文,发现非常详细,且内容使用。尤为难得,还直接拓展了 TBtools 的一个功能痛点(没有批量化反向互补功能!)。Chuhao 开发的这个插件,直接填补了这个缺憾,同时还做了多线程加速,我用了下,非常方便,非常快!现在插件已经上传到商店,感兴趣的朋友可下载使用。另,欢迎大伙学习这篇博文后,也一起来开发插件,贡献力量,一起减除更多人的生信数据分析负担。


    前言

    相信很多学习生物信息学的人都会学习python。你可能遇到过这样的情况:

    在一个风和日丽的早上,你耗尽洪荒之力,写好了一个“反向互补”命令行工具,然后很激动地把代码发到群里面,分享给实验室其他人用。

    小伙伴就会跟你说:这个脚本要怎么用呀?然后,你就会解释道:首先,安装一个python,然后这样打开终端,然后这样输入参数……。

    小伙伴说:“嗯,我先试一下”。然后一顿操作,在不知名网站上下载了个“python”安装包,把python安装好,还付送了一堆4XX9小游戏之类的软件。

    如无意外,过一会,小伙伴就会跑过来问你,“我输入命令,怎么报错了”?

    你仔细地检查,发现如下问题:

    • 安装了python2而不是python3
    • 那行命令没有在特定工作目录
    • 命令的某个单词少了一个字母
    • 某两个参数之间没有空格

    一顿操作过后,问题解决了,你还很详细地给小伙伴解释了其中的原理。能帮助到实验室的小伙伴,你很开心,回到工位上,准备迎接一天的工作。

    然后,噩梦来了。另外一个小伙伴又来问你同样的问题……

    这时候,我会告诉你:用pyinstaller打包你的工具,然后用TBtools的CLI Program Wrapper Creator来快速构建一个图形界面插件。

    5分钟把插件打包好,直接把插件扔给小伙伴们,在群里说:“我项目需求,顺手写了个工具,有需要的拿去。” 然后潇洒离去。

    下面我将用实际例子给大家介绍,如何操作。

    python反向互补脚本

    下面的脚本实现了单条序列的反向互补。为了减少代码量,我使用了biopython来进行fasta序列的读写和操作。接下来,我要把这个工具打包成TBtools插件。

    import sys
    from Bio import SeqIO
    
    infile = sys.argv[1]
    outfile = sys.argv[2]
    
    seq = SeqIO.read(infile, 'fasta')
    seq.seq = seq.seq.reverse_complement()
    
    with open(outfile, "w") as f:
        SeqIO.write(seq, f, "fasta")
    

    安装pyinstaller

    假设你已经安装好了python,进入cmd或者powershell,输入以下命令,即可安装pyinstaller以及脚本所依赖的biopython

    注意:如果你的python环境中已经安装了很多别的包,那么pyinstaller打包的时候会把一些不必要的包打包进来。这种情况下,建议使用virtualenv来新建一个新的环境(如果你是刚刚才安装的python,那就没必要做这一步了):

    py.exe -m pip install virtualenv
    
    py.exe -m virtualenv my_env
    
    .\my_env\Scripts\activate # 激活环境。激活后可以看到命令行左边多了(my_env)。
    
    # 如果激活失败,那就尝试不要用powershell,转用cmd(新建一个cmd窗口或者在powershell中直接输入cmd即可)。
    

    环境激活之后,安装所需的软件。这里除了pyinstaller,还安装了biopython,这是这个脚本中用到的。

    py.exe -m pip install pyinstaller biopython
    

    一般来说,安装完后,在cmd或者powershell下运行下面的命令可以打印出帮助信息。

    pyinstaller -h
    

    如果不行,那就试试下面的(注意大小写):

    py.exe -m PyInstaller -h
    

    编写脚本需要注意的问题

    参数传递

    可以使用位置参数(参数前不带“-”的)和长参数(参数前带“--”的)。如果只有位置参数,就直接用sys.argv;如果要用到长参数,推荐使用argparse

    值得注意的是,当argparsemultiprocessing一起使用的时候,需要使用parser.parse_know_args(),而不能直接使用parser.parse_args(),否则传递参数的时候会出错。

    多线程

    使用到多线程时,主程序需要用if __name__ == '__main__':保护起来。下面一行紧接着freeze_support()

    调用其他工具

    假如我的程序需要调用其他二进制文件,只需要把exe文件放在与脚本同一个目录下即可。TBtools运行脚本的时候,会自动把脚本所在目录添加到环境变量,于是在脚本中可以不需要指定二进制文件所在的路径。

    调用外部命令,注意给输入、输入文件路径加引号,防止输入文件路径中有空格的问题。假设输入文件路径为infile = "C:\Use r\input.fasta",中间有个空格。那么,如果使用os.system(f'tool_name.exe {infile}')来调用就会有问题。需要在infile两边加上引号:os.system(f'tool_name.exe "{infile}"')

    值得注意的是,如果使用的是blastn.exe等TBtools已经有的二进制文件,则可以直接调用,不必打包到插件当中。

    代码修改

    下面的代码,在原来的基础上添加了多线程和使用argparse来解析参数。请注意注释部分。

    import argparse
    from multiprocessing import Pool, freeze_support
    from Bio import SeqIO
    
    def rc(seq):
        seq.seq = seq.seq.reverse_complement()
        return seq
    
    if __name__ == '__main__': # 使用到多线程时,这一行必须加。下面一行紧接着“freeze_support()”
        freeze_support() 
        
        parser = argparse.ArgumentParser()
        parser.description = "多线程反向互补"
        parser.add_argument("--threads", default=1, type=int, help="Number of threads")
        parser.add_argument("input", help="Input fasta file")
        parser.add_argument("output", help="Output fasta file")
        
        args, unparsed = parser.parse_known_args() 
        # argparse和多线程搭配使用的时候,这里需要使用parse_know_args(),
        # 而不能直接使用parse_args(),否则传递参数的时候会出错。
    
        seqs = SeqIO.parse(args.input, 'fasta')
        with Pool(processes=args.threads) as pool:
            seqs_rc = pool.map(rc, seqs)
            pool.close()
            pool.join()
    
        with open(args.output, "w") as f:
            for seq in seqs_rc:
                SeqIO.write(seq, f, "fasta")
    

    打包

    具体操作

    在py脚本所在目录,按住“shift”键,然后右键点击文件浏览器的空白处,点击“在此处打开命令窗口”,就能进入终端,并自动切换工作目录为当前目录。

    运行以下命令,即可打包:

    pyinstaller -D .\multiprocess_rc.py
    
    # 如果不行,就用下面的:
    # py.exe -m PyInstaller -D .\multiprocess_rc.py
    

    打包完成,可以看到当前目录多了两个文件夹和一个文件:

    其中dist文件夹里面就是我们打包好的工具。里面长这样。里面的multiprocess_rc.exe就是程序的入口,其他文件是该程序依赖的资源,必须和主程序放在同一个目录。:

    命令解析

    在这个行命令中,我传递了-D.\multiprocess_rc.py两个参数给pyinstaller

    1. -D 参数是指要打包成一个文件夹,把所有依赖的dll等文件放在同一个文件夹中。另外一种方式是-F,指定-F参数可以把全部文件打包成单个的exe文件。虽然-F参数打包出来的文件看上去很干净,其实在实际运行的时候还是会把exe文件里面的东西释放到一个临时文件夹中,然后再运行,而且会引入一些额外的bug。所以,我推荐使用-D参数。

    2. .\multiprocess_rc.py 就是脚本的主程序。如果有多个模块,只需要输入主程序即可。打包工具会自动识别主程序中有import到的其他脚本,一起打包进去。

    其他实用参数

    如果你需要调用其他二进制文件,比如说tool.exe。你可以把tool.exe放在和脚本同一目录,然后打包的时候增加以下参数:--add-data "tool.exe;tool.exe"。这样就可以把tool.exe一起放在打包好的文件夹中了。当然你也可以手动复制过去,不过如果涉及到多次打包,就会麻烦一丢丢。

    输出文件

    • dist 目录:里面有打包好的软件。

    • build 目录:打包过程中生成的临时文件,可以删掉。

    • *.spec 文件:打包相关的配置文件。如果重复打包,可以直接把这个文件代替掉脚本名字,传递给pyinstaller,就不用再写那些参数了。

    小技巧

    常常会遇到需要打包、测试多次的时候。这时候,把打包和测试相关的命令写入到一个.bat文件中是比较方便的。这样直接双击.bat文件就可以重新打包,无需重新输入命令。

    关于pyinstaller的更多信息,请参考:

    测试pyinstaller打包结果

    进入dist/multiprocess_rc/目录,打开cmd,执行以下命令:

    .\multiprocess_rc.exe --threads 4 .\input.fasta output.fasta
    

    可以得到输出结果,代表运行成功。检查文件结果,也确实是反向互补了:

    input.fasta:

    >test
    ATCGGGTTCCAA
    >test1
    ATCGGGTTCCAA
    >test2
    ATCGGGTTCCAA
    >test3
    ATCGGGTTCCAA
    >test4
    ATCGGGTTCCAA
    

    output.fasta:

    >test
    TTGGAACCCGAT
    >test1
    TTGGAACCCGAT
    >test2
    TTGGAACCCGAT
    >test3
    TTGGAACCCGAT
    >test4
    TTGGAACCCGAT
    

    打包TBtools插件

    在插件商店安装好CLI Program Wrapper Creator后,从Tbtools的菜单栏Others > Plugin中即可看到。点击进去,参照下方的设置:

    配置完成,点击“Refresh”就可以刷新界面。还可以直接在界面中运行程序,非常方便。如果配置到一半要去吃饭,可以按下方的“Save Config”暂时把界面设置保存为文件,下次可以直接用“Load Config”来加载,省去很多时间。

    测试完成,点击右下角的“Export Plugin”,即可导出插件。导出的文件实际上是一个zip压缩文件。建议导出的时候不要加任何后缀,这样后面安装插件时,菜单栏上名字就会带有后缀。导出之后,再重新添加“.zip”后缀。

    导出后,进入Others > Install Plugin 安装插件,然后就可以使用了。

    把序列粘到Input输入框,点击开始,就可以看到下方的反向互补序列了!

    这里我忽略了很多UI设计界面使用的细节,详情可以回头看看公众号前几天的推文,有CJ的详细教程。

    总结

    把经常要做的、重复性的东西简单化、流程化、自动化,或许可以让大家把更多的时间投入到科学问题的研究中。

    相关文章

      网友评论

        本文标题:手把手 | 教你打包Python脚本并用TBtools完成程序界

        本文链接:https://www.haomeiwen.com/subject/kayxfdtx.html