从python运行命令的便利包
cmd的Python项目详细描述
CMDY
从python运行命令的一个方便的包
安装
# latest version pip install git+https://github.com/pwwang/cmdy # released version pip install cmdy
为什么在sh
之外还有一个?
oncotator
不与sh
一起运行,无论我尝试了什么。- 无法用烘焙命令替换参数,请参见以下示例:
fromshimportlsls=ls.bake(l=True)print(ls())# ls -l# but now I somehow want to run `ls` (without `-l`) command with `ls()`ls(l=False)# not work
- 无法保存命令的配置,因为命令有其可靠的首选项。
- 无法指定可执行文件的完整路径。
- 没有管道/重定向标记。
基本用法
fromcmdyimportlsprint(ls())
参数
像sh
,cmdy
可以有非关键字参数,但首选关键字参数。
fromcmdyimporttartar("cvf","/tmp/test.tar","/my/home/directory/")
带关键字参数
curl("http://duckduckgo.com/",o="page.html",silent=True)# curl http://duckduckgo.com/ -o page.html --silent
order关键字参数:
curl("http://duckduckgo.com/","-o","page.html","--silent")# or fromcollectionsimportOrderedDictcurl("http://duckduckgo.com/",OrderedDict([('o','page.html'),('silent',True)]))
关键字参数的前缀和分隔符:
fromcmdyimportbedtools,bcftools,lsbedtools.intersect(wa=True,wb=True,a='query.bed',b=['d1.bed','d2.bed','d3.bed'],names=['d1','d2','d3'],sorted=True,_prefix='-')#bedtools intersect -wa -wb -a query.bed -b d1.bed d2.bed d3.bed -names d1 d2 d3 -sortedbcftools.query(_=['a.vcf','b.vcf'],H=True,format='%CHROM\t%POS\t%REF\t%ALT\n')# bcftools query --format '%CHROM\t%POS\t%REF\t%ALT\n' -H a.vcf b.vcf# _prefix defaults to 'auto' ('-' for short options, '--' for long)# You may also define arbitrary prefix:# command(a = 1, bc = 2, _prefix = '---')# command ---a 1 ---bc 2ls(l=True,block_size='KB',_sep='auto')# ls -l --block-size=KB# _sep defaults to ' '. 'auto' means ' ' for short options, '=' for long
一个命令中前缀和分隔符的不同组合:
fromcmdyimportjava# Note this is just an example for old verion picard. Picard is changing it's stylejava({'jar':'picard.jar','_prefix':'-','_sep':' '},'SortSam',I='input.bam',O='sorted.bam',SORTED_ORDER='coordinate',_raw=True,_prefix='',_sep='=')# java -jar picard.jar SortSam I=input.bam O=sorted.bam SORT_ORDER=coordinate# The first dictionary usees _prefix and _sep in itself if specified, otherwise uses the ones specified with kwargs.# _raw = True keeps SORTED_ORDER as it is, otherwise, it'll be transformed into SORTED-ORDER# This is useful when some command has option like '--block-size', but you can still use 'block_size' as keyword argument.
列表参数的重复键:
fromcmdyimportsortsort(k=['1,1','2,2n'],_='a.bed',_dupkey=True)# sort -k 1,1 -k 2,2n a.bed
返回代码和异常
fromcmdyimportxx()
... ... raise CmdyReturnCodeException(self) │ └ └ <class 'cmdy.CmdyReturnCodeException'> cmdy.CmdyReturnCodeException: Unexpected RETURN CODE 127, expecting: [0][PID]38254[CMD] x [STDERR] /bin/sh: x: command not found
您可以使用try/catch来捕获它:
fromcmdyimportx,CmdyReturnCodeExceptiontry:x()exceptCmdyReturnCodeExceptionasexprint('Command returned %s'%ex.cmdy.rc)
您可以通过以下方式允许多个返回代码:x(_okcode = [0, 127])
或x(_okcode = '0,127')
重定向
fromcmdyimportifconfigifconfig(_out="/tmp/interfaces")# or you can use shell redirection notationifconfig(_out=">")>"/tmp/interfaces"# or # ifconfig(_out = "/tmp/interfaces")## appendifconfig(_out=">")>>"/tmp/interfaces"# or# ifconfig(_out_ = "/tmp/interfaces")# redirect stderrifconfig(_err=">")>"/tmp/ifconfig.errors"# or ifconfig(_err = "/tmp/ifconfig.errors")
输出迭代
fromcmdyimporttailforlineintail(_='test.txt',_iter=True):print(line)
后台进程
对于要在非块模式下运行的命令,可能需要使用_bg
关键字:
forlineintail(_='test.txt',_bg=True,_iter=True):print(line)
# blockssleep(3)print("...3 seconds later")# doesn't blockp=sleep(3,_bg=True)print("prints immediately!")p.wait()print("...and 3 seconds later")
后台进程的回调:
importtimefromcmdyimportsleepdefcallback(cmdy):print(cmdy.rc)p=sleep(3,_bg=callback)p.wait()# prints 0
烘烤
fromcmdyimportjavapicard=java.bake(dict(jar='picard.jar',_sep=' ',_prefix='-'))#picard.SortSam(...)
与sh
不同,cmdy
保存关键字参数,并在烘焙为新命令时更新它们。这使它能够用新的baked命令替换一些参数。
fromcmdyimportlsls=ls.bake(l=True)# or ls = ls(l = True, _bake = True)ls()# ls -l# I don't want -l anymorels(l=False)
注意,非关键字参数是不可更新的。
ls=ls.bake('-l')ls()# ls -l# Not work, still ls -lls(l=False)
烘焙整个模块:
importcmdycmdy=cmdy(_fg=True)# all commands under new module is running at foreground (stdout = sys.stdout, stderr = stderr)fromcmdyimportlsls()
管道
# get the permission columnls(l=True,_pipe=True)|cut(f=1,_fg=True)
子命令
fromcmdyimportgitprint(git.branch(v=True))
别名/为命令指定可执行文件的完整路径
fromcmdyimportfc_cache,pythonfc_cache(_exe='fc-cache',vf='~/.fonts/',_prefix='-')# fc-cache -vf ~/.fonts/python(_exe='/home/user/miniconda3/bin/python3',version=True)# /home/user/miniconda3/bin/python3 --version
始终将fc_cache
别名设为fc-cache
,并将python
点设为/home/user/miniconda3/bin/python3
,将以下内容添加到~/.cmdy.ini
[fc_cache]_exe=fc-cache[python]_exe=/home/user/miniconda3/bin/python3
那么您就不需要再关心路径了:
fromcmdyimportfc_cache,pythonfc_cache(vf='~/.fonts/',_prefix='-')# fc-cache -vf ~/.fonts/python(version=True)# /home/user/miniconda3/bin/python3 --version
配置
cmdy
将首先加载默认参数:
{'_okcode':0,'_exe':None,'_sep':' ','_prefix':'auto','_dupkey':False,'_bake':False,'_iter':False,'_pipe':False,'_raw':False,'_timeout':0,'_encoding':'utf-8','_bg':False,'_fg':False,'_out':None,'_out_':None,'_err':None,'_err_':None}
然后尝试加载$HOME/.cmdy.ini
、./.cmdy.ini
和以CMDY_
开头的环境变量,以便可以用临时环境变量覆盖配置。
例如,我希望始终使用原始关键字选项:
~/.cmdy.ini
[default]_raw: True
ontotator.py
:
fromcmdyimportoncotatoroncotator(log_name='/path/to/log',...)# oncotator --log_name LOG_NAME ...# you don't have to specify _raw = True any more.
使用环境变量覆盖设置:
exportCMDY_oncotator__raw=False python oncotator.py # will run:# oncotator --log-name LOG_NAME ...# ^