[英]How to run a separate function not included in if __name__==“__main__” from the command line?
[英]How to make a python module with function to run command line tools in parallel (w/o using if __name__ == '__main__': so it's importable)?
我想制作一个具有便利功能的python模块,以便在Windows上使用Python 3.7并行运行命令。 (对于az cli命令)
我想要一个使该功能:
这是出乎意料的困难,我认为以前在旧版本的python中是不可能的吗? (我看到几个2-8岁的问答,说if __name__==__main__:
必须使用if __name__==__main__:
进行并行处理,但是我发现在制作可导入模块时,这种方法无法始终如一地可预测。
def removeExtraLinesFromString(inputstring):
stringtoreturn = ""
for line in inputstring.split("\n"):
if len(line.strip()) > 0: #Only add non empty lines to the stringtoreturn
stringtoreturn = stringtoreturn + line
return stringtoreturn
def runCmd(cmd): #string of a command passed in here
from subprocess import run, PIPE
stringtoreturn = str( run(cmd, shell=True, stdout=PIPE).stdout.decode('utf-8') )
stringtoreturn = removeExtraLinesFromString(stringtoreturn)
return stringtoreturn
def exampleOfParrallelCommands():
if __name__ == '__main__': #I don't like this method, because it doesn't work when imported, refractoring attempts lead to infinite loops and unexpected behavior.
from multiprocessing import Pool
cmd = "python -c \"import time;time.sleep(5);print('5 seconds have passed')\""
cmds = []
for i in range(12): #If this were running in series it'd take at least a minute to sleep 5 seconds 12 times
cmds.append(cmd)
with Pool(processes=len(cmds)) as pool:
results = pool.map(runCmd, cmds) #results is a list of cmd output
print(results[0])
print(results[1])
return results
当我尝试将其作为模块导入时(由于使用if语句而导致无法正常运行),因此我尝试重写代码以移动if语句,我想我删除了它一次,这导致我的计算机进入循环直到我关闭程序。 __name__ == '__main__'
我可以将模块导入另一个python程序,但是要完成该工作,我必须添加__name__ == '__main__'
,这非常直观。
我几乎放弃了,但是经过两天的大量python网站和SO帖子搜索后,我在这次问答中看到用户jfs的代码( Python:并行执行cat子进程 )后,终于找到了解决方法,我修改了他的代码,最好适合我的问题的答案。
工具箱
def removeExtraLinesFromString(inputstring):
stringtoreturn = ""
for line in inputstring.split("\n"):
if len(line.strip()) > 0: #Only add non empty lines to the stringtoreturn
stringtoreturn = stringtoreturn + line
return stringtoreturn
def runCmd(cmd): #string of a command passed in here
from subprocess import run, PIPE
stringtoreturn = str( run(cmd, shell=True, stdout=PIPE).stdout.decode('utf-8') )
stringtoreturn = removeExtraLinesFromString(stringtoreturn)
return stringtoreturn
def runParallelCmds(listofcommands):
from multiprocessing.dummy import Pool #thread pool
from subprocess import Popen, PIPE, STDOUT
listofprocesses = [Popen(listofcommands[i], shell=True,stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True) for i in range(len(listofcommands))]
#Python calls this list comprehension, it's a way of making a list
def get_outputs(process): #MultiProcess Thread Pooling require you to map to a function, thus defining a function.
return process.communicate()[0] #process is object of type subprocess.Popen
outputs = Pool(len(listofcommands)).map(get_outputs, listofprocesses) #outputs is a list of bytes (which is a type of string)
listofoutputstrings = []
for i in range( len(listofcommands) ):
outputasstring = removeExtraLinesFromString( outputs[i].decode('utf-8') ) #.decode('utf-8') converts bytes to string
listofoutputstrings.append( outputasstring )
return listofoutputstrings
main.py
from toolbox import runCmd #(cmd)
from toolbox import runParallelCmds #(listofcommands)
listofcommands = []
cmd = "ping -n 2 localhost"
listofcommands.append(cmd)
cmd = "python -c \"import time;time.sleep(5);print('5 seconds have passed')\""
for i in range(12):
listofcommands.append(cmd) # If 12 processes each sleep 5 seconds, this taking less than 1 minute proves parrallel processing
outputs = runParallelCmds(listofcommands)
print(outputs[0])
print(outputs[1])
输出:
用32个字节的数据Ping neokylesPC [:: 1]:来自:: 1:time <1ms的响应来自:: 1:time <1ms对于:: 1的Ping统计信息:数据包:已发送= 2,已接收= 2,丢失= 0(损失0%),大约往返时间(以毫秒为单位):最小值= 0ms,最大值= 0ms,平均值= 0ms
5秒过去了
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.