并行运行函数,但从上一个函数继承动态数据

时间:2018-07-10 21:32:46

标签: python parallel-processing

我正在尝试同时运行多个功能:

-或所谓的函数,因为它们属于一个类:

from sh import tail
data = {}
class my_Class():
    def __init__(self):
        """Nothing to declare for initializing"""
    def get_data(self, filepath):
        """I'm trying to import the data from several files"""
        for line in tail("-f", "-n 1", filepath, _iter=True):
            data[filepath] = line
            print(data)
my_Class().get_data("path/to/file") #call 1
my_Class().get_data("path/to/another/file") #call 2
# ... 14 similar calls

我希望每个调用都将其数据附加到字典中。因此,当我打电话时:

my_Class().get_data("path/to/file") #call 1
my_Class().get_data("path/to/another/file") #call 2
# ... 14 similar calls

结果应打印:

#1 {'filepath1' : line}
#2 {'filepath1' : line, 'filepath2' : line}
#3 {'filepath1' : line, 'filepath2' : line, 'filepath3' : line}
# ... 13 more

同时,我希望字典数据的内容{...}保持动态变化;因为文件中的数据很灵活。例如:

#1 {'filepath1' : line}
#2 {'filepath1' : last_line_in_the_file}, 'filepath2' : line}
#3 {'filepath1' : last_line_in_the_file, 'filepath2' : last_line_in_the_file, 'filepath3' : line}
# ... 13 more

我已经检查了这些帖子:但是它没有按照我的要求进行; Python: How can I run python functions in parallel?How to do parallel programming in Python 谢谢!请告诉我是否听起来有些晦涩

1 个答案:

答案 0 :(得分:0)

听起来您在这里要求两件事:

  1. 如何并行运行任务,
  2. 如何在这些任务之间共享(可变)值。

对于第一个,您猜到了答案是线程。对于某些程序,这不是答案,因为他们花费大量时间在Python中进行大量的CPU计算,或者因为您需要成千上万的任务而不是少数几个。但是在这里,只需将每个线程作为线程运行即可。

代替此:

my_Class().get_data("path/to/file") #call 1
my_Class().get_data("path/to/another/file") #call 2

…您创建线程:

t1 = threading.Thread(target=my_Class().get_data, args=

(“路径/至/文件”,))     t2 = threading.Thread(target = my_Class()。get_data,args = (“路径/到/另一个/文件”,))

…然后启动它们:

t1.start()
t2.start()

…然后等待它们全部完成(在这种情况下,这显然将永远存在,因此您可以在此处简化事情……):

t1.join()
t2.join()

现在,如何在线程之间共享可变数据?

首先,您可以从不同的线程访问和变异相同的值。但总的来说,除非您不知道不需要一个值,否则就希望对每个值进行锁定。

如果您只关心Windows,macOS,Linux和BSD上的CPython,那么将具有字符串键的字符串值插入dict对象是不需要锁的事情之一。 printstdout是另一个。而这些是您共享的唯一内容。因此,您实际上不需要在这里锁。一切都会起作用。

但是,由于您可能不知道dict以这种方式是安全的,所以让我们看看如何使用锁。

data = {}
data_lock = threading.Lock()

# etc.

def get_data(self, filepath):
    """I'm trying to import the data from several files"""
    for line in tail("-f", "-n 1", filepath, _iter=True):
        with data_lock:
            data[filepath] = line
            print(data)

仅此而已。

事情会变得更加复杂。例如,您实际上不需要在这里呆多长时间。如果您有30个线程,则很有可能其中一个正在尝试抓住该锁以添加新值,而另一个线程已经从data中创建了一个字符串,并花了时间打印该字符串(打印到stdout的速度很慢),但是尚未释放锁定。如果是这样,您可以通过分解来获得更多的并行性:

def get_data(self, filepath):
    """I'm trying to import the data from several files"""
    for line in tail("-f", "-n 1", filepath, _iter=True):
        with data_lock:
            data[filepath] = line
        with data_lock:
            datastr = str(data)
        print(datastr)

但这真的很复杂。关于线程的困难部分是当您必须编写单独的锁时,因为您有在线程之间传递的单独数据,依此类推。对于这样的简单情况,实际上非常简单。