Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python调用函数和主程序_Python_Multithreading_Concurrency_Multiprocessing_Python Asyncio - Fatal编程技术网

Python调用函数和主程序

Python调用函数和主程序,python,multithreading,concurrency,multiprocessing,python-asyncio,Python,Multithreading,Concurrency,Multiprocessing,Python Asyncio,我正在以设定的频率(例如8hz)收集数据。这些数据会被修改、存储,然后偶尔发送出去写入 由于流式传输/写入数据,我遇到了时间问题。当程序写入数据(每5秒一次)时,所需时间超过1/8hz(0.125s)。这会造成数据采集时间的延迟 我想做的是调用我的write函数并让它运行,但也允许我的主程序继续运行,这样就不会延迟计时 我尝试过几种不同的方法,但运气不佳:线程、多处理和异步。但很可能是我用错了 我正在做的事情的一个非常简化的版本: def main(): 尽管如此: curTime=dateti

我正在以设定的频率(例如8hz)收集数据。这些数据会被修改、存储,然后偶尔发送出去写入

由于流式传输/写入数据,我遇到了时间问题。当程序写入数据(每5秒一次)时,所需时间超过1/8hz(0.125s)。这会造成数据采集时间的延迟

我想做的是调用我的write函数并让它运行,但也允许我的主程序继续运行,这样就不会延迟计时

我尝试过几种不同的方法,但运气不佳:线程、多处理和异步。但很可能是我用错了

我正在做的事情的一个非常简化的版本:

def main():
尽管如此:
curTime=datetime.datetime.now()
当curTime8*5:
writeData(hdata)#发送要写入的数据-耗时太长,导致下一个样本的延迟>上一个样本的0.125s。
nextTime=curTime+datetime.TIMEDERTA(微秒=125000)#调整下一次测量时间-上次收集数据后0.125s。
在上述代码中。我想调用writeData并让该函数完成它的任务,但要让我的主函数继续运行并收集更多数据。writeData可以用多长时间,假设它比我的写入间隔快;现在是这样

我在用蟒蛇3

希望这是足够的信息提供一些指导


非常感谢您提供的任何帮助。

您使用异步编程解决问题的方法是正确的。Python中的异步编程本身就很棘手,因为使用线程(
线程
)、进程(
多处理
)或协同程序(
异步
)实现的并发性存在主要差异。没有“正确”的方法,您选择最适合当前用例的方法

您的问题既有IO绑定(数据获取和写入)任务,也有CPU绑定(数据处理)任务,它们可以独立并行运行。这是你可以做到的。也许这不是最优雅的解决方案,但它将向您展示如何处理此类问题

在我们的解决方案中,我们将线程用于IO绑定的任务,进程用于CPU绑定的任务。就我个人而言,我更喜欢在所有任务中使用线程,但在这种情况下,我们将无法充分发挥现代多核CPU的所有功能来并行化数据处理,因为它的复杂性

首先,让我们在可执行脚本中导入所需的模块:

import time
import random
import signal
from threading import Thread
from multiprocessing.pool import Pool
from queue import Queue, Empty
我们解决的问题是一个问题。主线程以固定的时间间隔获取数据并将其放入队列。处理器线程从队列中获取数据,并将其提交给工人池进行处理,然后收集结果并将其放入另一个队列。写入线程不断读取该队列,最终保存数据。现在,我们添加了一些常量—一些并行运行的工作进程和以秒为单位的数据获取间隔:

WORKERS = 4
FETCH_INTERVAL = 1
下面是主线程,它负责在无限循环中每隔
FETCH_INTERVAL
secs获取数据:

def main():
    raw_data = Queue()
    processor = Thread(target=process, args=(raw_data,))
    processor.start()
    i = 0

    try:

        while True:
            t_fetch = time.time()

            # Simulate the data fetching:
            time.sleep(0.5)
            data = i, random.random()
            print("[main] Fetched raw data:", data)

            raw_data.put(data)
            t_elapsed = time.time() - t_fetch

            if t_elapsed < FETCH_INTERVAL:
                time.sleep(FETCH_INTERVAL - t_elapsed)
            else:
                print("[error] The fetch interval is too short!")

            i = i + 1

    except KeyboardInterrupt:
        print("shutting down...")
    finally:
        raw_data.put(None)
        processor.join()

if __name__ == "__main__":
    main()
这里,我们创建一个
proc_data
队列,它将保存
writer
线程的数据处理结果。
writer
线程运行一个
write
函数,我们稍后将定义该函数。一旦
writer
线程启动,我们将创建一个
worker
进程的
pool
。在这里,我们使用
init_worker
函数作为
Pool
进程初始值设定项,以忽略在主线程中处理的工作进程中的键盘中断:

def init_worker():
    signal.signal(signal.SIGINT, signal.SIG_IGN)
一旦创建了进程池,我们通过调用下面定义的
dequeue\u data
函数,进入一个无限循环,不断地从
raw\u data
队列中排出数据批。然后将数据批提交到工作池进行处理。下面将定义
process\u data
功能。然后,我们收集结果并将其放入
proc_data
队列,该队列由
writer
线程读取。如果数据批处理中存在
None
,则处理将被中断,我们将等待
编写器
线程完成。
dequeue\u data
功能定义如下:

def dequeue_data(data_queue, batch_size):
    items = []

    for _ in range(batch_size):
        try:
            item = data_queue.get(block=False)
        except (KeyboardInterrupt, Empty):
            break

        items.append(item)

    return items
在这里,您可以看到它只是尝试从
数据队列
获取并返回最多
批大小
数据点。如果没有数据,它将返回一个空列表。
process_data
功能只休眠1-5秒:

def process_data(data):

    if data is None:
        return

    # Simulate the data processing:
    time.sleep(random.randint(1, 5))

    return data
最后,我们定义了在
writer
线程中运行的
write
函数:

def process(raw_data):
    proc_data = Queue()
    writer = Thread(target=write, args=(proc_data,))
    writer.start()

    with Pool(WORKERS, init_worker) as pool:

        while True:
            data_batch = dequeue_data(raw_data, batch_size=WORKERS)

            if not data_batch:
                time.sleep(0.5)
                continue

            results = pool.map(process_data, data_batch)
            print("[processor] Processed raw data:", results)

            for r in results:
                proc_data.put(r)

            if None in data_batch:
                break

    print("joining the writer thread...")
    writer.join()
def write(proc_data):

    while True:
        data = proc_data.get()

        if data is None:
            break

        # Simulate the data writing:
        time.sleep(random.randint(1, 2))
        print("[writer] Wrote processed data:", data)
一旦无限循环从
proc_data
队列中获取
None
,无限循环就会停止。现在,我们将提供的所有代码保存在一个脚本中,然后运行并检查其输出:

[main] Fetched raw data: (0, 0.8092310624924178)
[main] Fetched raw data: (1, 0.8594148294409398)
[main] Fetched raw data: (2, 0.9059856675215566)
[main] Fetched raw data: (3, 0.5653361157057876)
[main] Fetched raw data: (4, 0.8966396309003691)
[main] Fetched raw data: (5, 0.5772344067614918)
[processor] Processed raw data: [(0, 0.8092310624924178)]
[main] Fetched raw data: (6, 0.4614411399877961)
^Cshutting down...
[writer] Wrote processed data: (0, 0.8092310624924178)
[processor] Processed raw data: [(1, 0.8594148294409398), (2, 0.9059856675215566), (3, 0.5653361157057876), (4, 0.8966396309003691)]
[writer] Wrote processed data: (1, 0.8594148294409398)
[writer] Wrote processed data: (2, 0.9059856675215566)
[processor] Processed raw data: [(5, 0.5772344067614918), (6, 0.4614411399877961), None]
joining the writer thread...
[writer] Wrote processed data: (3, 0.5653361157057876)
[writer] Wrote processed data: (4, 0.8966396309003691)
[writer] Wrote processed data: (5, 0.5772344067614918)
[writer] Wrote processed data: (6, 0.4614411399877961)

main
线程以固定的时间间隔获取数据,而
处理器
以并行方式批量处理数据,而
编写器
保存结果。当我们点击
Ctrl-C
时,
main
线程停止提取数据,然后,
处理器
线程完成了对其余提取数据的处理,并开始等待
写入程序
线程完成将数据写入磁盘。

尝试使用异步编程解决问题的方法是正确的。Python中的异步编程本身就很棘手,因为使用线程(
threading