【问题标题】:running script multiple times simultaniously in python 2.7在python 2.7中同时多次运行脚本
【发布时间】:2013-04-05 18:03:58
【问题描述】:

您好,我正在尝试多次运行脚本,但我希望这可以同时发生,据我所知,我是一起使用子进程和线程 但是,当我运行它时,它看起来仍然是按顺序执行的,有人可以帮助我,以便我可以让它一遍又一遍地同时运行相同的脚本吗? 它实际上是否有效并且真的很慢?

edit 现在忘记了最后一段代码

这是我目前所拥有的

import os
import datetime
import threading
from subprocess import Popen

today = datetime.date.today()
os.makedirs("C:/newscript_image/" + str(today))

class myThread(threading.Thread):
    def run(self):
        for filename in os.listdir('./newscript/'):
            if '.htm' in filename:
                name = filename.strip('.htm')

                dbfolder = "C:/newscript/db/" + name
                os.makedirs(dbfolder)

                Popen("python.exe C:/execution.py" + ' ' + filename + ' ' + name + ' ' + str(today) + ' ' + dbfolder)
myThread().start()

【问题讨论】:

  • 他们需要如何“同时”? subprocess 将愉快地异步执行进程。
  • 我认为您可能没有那里的所有代码。这会创建一个线程类,但实际上并不运行线程。看起来你也可以直接在 execution.py 中调用你需要的任何函数,而不是通过新的 python.exe 解释器调用它。
  • @MichaelGreene 感谢您指出我确实在我的代码底部有 myThread.start 只是忘了包含它,所以我的线程现在应该在 execution.py 脚本中完成脚本也只是运行另一个带有一些参数的脚本,例如 script1.py param1 然后下一行将是 script1.py param2 等等

标签: python asynchronous python-2.7 subprocess python-multithreading


【解决方案1】:

就我个人而言,我会使用multiprocessing。我会编写一个函数,它接受一个文件名并执行execution 的主要功能(可能通过导入execution 并在其中运行一些函数):

import multiprocessing
import execution
import datetime

#assume we have a function:
#exection.run_main_with_args(filename,name,today_str,dbfolder)

today = datetime.datetime.today()
def my_execute(filename):
    if '.htm' in filename:
       name = filename.strip('.htm')
       dbfolder = "C:/newscript/db/" + name
       os.makedirs(dbfolder)
       execution.run_main_with_args(filename,name,str(today),dbfolder)

p = multiprocessing.Pool()
p.map(my_execute,list_of_files_to_process)

【讨论】:

  • 有没有办法在不重写函数的情况下做到这一点?现在执行还调用了另一个脚本,并且那个脚本还调用了大约 10 个脚本来处理其他各种事情,或者如果它们都被组合成一个庞大的脚本,我是否必须重写每个脚本?
  • 您可以调用Popen 代码而不是execution.run_main_with_args。这个答案的核心思想是工作人员的多处理池并将文件列表映射到它上面,这样你就可以拥有一个工作人员池来进行处理,而不是运行 1 个额外的线程来进行处理。 mgilson 的解决方案只是避免了 Popen 的开销并以这种方式调用新的 python.exe 解释器。
【解决方案2】:

进行了一些快速测试。使用脚本的框架:

#!/usr/bin/env python

import os
import threading
from subprocess import Popen

class myThread(threading.Thread):
    def run(self):
        for filename in os.listdir("./newscript/"):
            if '.htm' in filename:
                Popen("./busy.sh")

myThread().start()

然后,我用一堆“.htm”文件填充了“newscript”文件夹,针对这些文件运行脚本。

“busy.sh”基本上在哪里:

#!/usr/bin/env bash
while :
do
    uptime >> $$
    sleep 1
done

您拥有的代码确实会触发在后台运行的多个进程。我使用包含 200 个文件的 newscript 文件夹执行此操作,我看到 200 个进程都在后台运行。

您指出您希望它们同时在后台运行。

在大多数情况下,并行进程在后台“大致”并行运行,但由于大多数常见操作系统的设置方式,“并行”更像是“近乎并行”或更通常称为异步。如果您非常仔细地查看访问时间,以这种方式产生的各种进程将各自轮流,但它们永远不会同时做某事。

这是需要注意的。特别是因为您正在访问由操作系统和底层文件系统控制的文件。

对于您要执行的操作:处理大量入站文件,您的操作方式基本上是在后台为出现的每个文件生成一个进程来处理文件。

所呈现的逻辑存在几个问题:

  1. 叉子炸弹情况的高风险,因为您的产卵是无限的,并且没有跟踪仍在产卵的东西。
  2. 通过调用和执行另一个程序来生成的方式会导致生成操作系统级别的进程,这会占用更多资源。

建议:

与其生成作业,不如将生成的文件处理代码转换为 Python 函数。将您的代码重新编写为一个守护进程,它监视文件夹并跟踪产生了多少进程,以便管理处理文件转换的后台进程级别。

在处理文件时,您会分离出一个 Python 线程来处理它,这将是一个比衍生出操作系统级线程更轻量级的替代方案。

【讨论】:

    【解决方案3】:

    稍微阐述一下mgilson的回答:

    假设我们有一个文件夹 example1。
    在 example1 中,我们有两个 python 脚本:
    execution.pyma​​in.py

    execution.py 的内容如下所示:

    import subprocess
    
    
    def run_main_with_args(filename,name,today,dbfolder):
        print('{} {} {}'.format('\nfilename: ',filename, ''))
        print('{} {} {}'.format('name: ',name, ''))
        print('{} {} {}'.format('today: ',today, ''))
        print('{} {} {}'.format('dbfolder: ',dbfolder, ''))
    
        outfile = dbfolder+ '/' + name + '.txt'
        with open (outfile, 'w') as fout:
            print('name', file=fout)
    

    另外,ma​​in.py 的内容如下所示:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # Author      : Bhishan Poudel; Physics Graduate Student, Ohio University
    # Date        : Aug 29, 2016
    #
    
    # Imports
    import multiprocessing,os,subprocess
    import datetime
    import execution  # file: execution.py
    
    #assume we have a function:
    #exection.run_main_with_args(filename,name,today_str,dbfolder)
    
    today = datetime.datetime.today()
    def my_execute(filename):
        if '.txt' in filename:
           name = filename.strip('.txt')
           dbfolder = "db/" + name
           if not os.path.exists(dbfolder): os.makedirs(dbfolder)
           execution.run_main_with_args(filename,name,str(today),dbfolder)
    
    
    
    p = multiprocessing.Pool()
    p.map(my_execute,['file1.txt', 'file2.txt'])
    

    然后,如果我们运行这个 ma​​in.py,它将以 parallel 的方式在所需目录中创建所需文件!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-23
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      相关资源
      最近更新 更多