Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/336.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 - Fatal编程技术网

Python在另一个函数返回结果后结束函数

Python在另一个函数返回结果后结束函数,python,Python,我可能完全错了,但这仍然是我所处的位置。我正在尝试搜索非常大的日志文件,在某些情况下可达30gb。我正在编写一个脚本来获取信息,并一直在使用多进程来加快速度。现在我正在测试同时运行两个函数,从顶部和底部搜索结果,这似乎是可行的。我想知道是否有可能停止一个函数,一个是另一个函数的结果。例如,如果top函数找到一个结果,它们都会停止。这样我就可以根据需要构建它 from file_read_backwards import FileReadBackwards from multiprocessing

我可能完全错了,但这仍然是我所处的位置。我正在尝试搜索非常大的日志文件,在某些情况下可达30gb。我正在编写一个脚本来获取信息,并一直在使用多进程来加快速度。现在我正在测试同时运行两个函数,从顶部和底部搜索结果,这似乎是可行的。我想知道是否有可能停止一个函数,一个是另一个函数的结果。例如,如果top函数找到一个结果,它们都会停止。这样我就可以根据需要构建它

from file_read_backwards import FileReadBackwards
from multiprocessing import Process
import sys

z = "log.log"

#!/usr/bin/env python
rocket = 0

def top():
    target = "test"
    with open(z) as src:
        found= None
        for line in src:
            if len(line) == 0: break #happens at end of file, then stop loop
            if target in line:
                found= line
                break
    print(found)

def bottom():
    target = "text"
    with FileReadBackwards(z) as src:
        found= None
        for line in src:
            if len(line) == 0: break #happens at end of file, then stop loop
            if target in line:
                found= line
                break
    print(found)


if __name__=='__main__':
     p1 = Process(target = top)
     p1.start()
     p2 = Process(target = bottom)
     p2.start()

以下是我在评论中提到的方法的概念证明:

import os
import random
import sys
from multiprocessing import Process, Value


def search(proc_no, file_name, seek_to, max_size, find, flag):
    stop_at = seek_to + max_size

    with open(file_name) as f:
        if seek_to:
            f.seek(seek_to - 1)
            prev_char = f.read(1)
            if prev_char != '\n':
                # Landed in the middle of a line. Skip back one (or
                # maybe more) lines so this line isn't excluded. Start
                # by seeking back 256 bytes, then 512 if necessary, etc.
                exponent = 8
                pos = seek_to
                while pos >= seek_to:
                    pos = f.seek(max(0, pos - (2 ** exponent)))
                    f.readline()
                    pos = f.tell()
                    exponent += 1

        while True:
            if flag.value:
                break
            line = f.readline()
            if not line:
                break  # EOF
            data = line.strip()
            if data == find:
                flag.value = proc_no
                print(data)
                break
            if f.tell() > stop_at:
                break


if __name__ == '__main__':
    # list.txt contains lines with the numbers 1 to 1000001
    file_name = 'list.txt'
    info = os.stat(file_name)
    file_size = info.st_size

    if len(sys.argv) == 1:
        # Pick a random value from list.txt
        num_lines = 1000001
        choices = list(range(1, num_lines + 1))
        choices.append('XXX')
        find = str(random.choice(choices))
    else:
        find = sys.argv[1]

    num_procs = 4
    chunk_size, remainder = divmod(file_size, num_procs)
    max_size = chunk_size + remainder
    flag = Value('i', 0)
    procs = []

    print(f'Using {num_procs} processes to look for {find} in {file_name}')

    for i in range(num_procs):
        seek_to = i * chunk_size
        proc = Process(target=search, args=(i + 1, file_name, seek_to, max_size, find, flag))
        procs.append(proc)

    for proc in procs:
        proc.start()

    for proc in procs:
        proc.join()

    if flag.value:
        print(find, 'found by proc', flag.value)
    else:
        print(find, 'not found')

在阅读了关于使用多处理和多线程读取文件的各种文章[1]之后,由于潜在的磁盘抖动和序列化读取,这两种方法似乎都不是很好的方法。因此,这里有一种不同的、更简单的方法,它的速度要快得多(至少对于我尝试使用的有一百万行的文件):

我很好奇30GB日志文件的性能如何


[1] 包括使用
多处理.Pool
和回调函数的简单示例。 在返回结果后终止剩余的池进程

使用这种方法,可以添加任意数量的进程,从文件中的不同偏移量进行搜索

import math
import time

from multiprocessing import Pool
from random import random


def search(pid, wait):
    """Sleep for wait seconds, return PID
    """
    time.sleep(wait)
    return pid


def done(result):
    """Do something with result and stop other processes
    """
    print("Process: %d done." % result)
    pool.terminate()
    print("Terminate Pool")


pool = Pool(2)
pool.apply_async(search, (1, math.ceil(random() * 3)), callback=done)
pool.apply_async(search, (2, math.ceil(random() * 3)), callback=done)

# do other stuff ...

# Wait for result
pool.close()
pool.join()  # block our main thread

这基本上与Blurp的答案相同,但我将其缩短了一点,使其更具一般性。正如你们所看到的,顶部应该是一个无限循环,但底部会立即停止顶部

from multiprocessing import Process
valNotFound = True
def top():
    i=0
    while ValNotFound:
        i += 1


def bottom():
    ValNotFound = False


p1 = Process(target = top)
p2 = Process(target = bottom)
p1.start()
p2.start()

您必须将共享标志传递给这两个进程。当一个人发现结果时,他就会设定它;另一个看到它已被设置并退出。另外,我想看看这个
FileReadBackwards
。看起来更像是要将文件分割成块,并向前读取每个块。没有实际的分割。您可以使用与
top()
相同的逻辑查找到文件的中点,然后从那里开始。您不必逐字拆分它。您只需找到正确的偏移量,然后查找它,将偏移量传递给两个进程。关于限制,grep或ag是否受到限制?您阅读的是哪种存储?我做这件事的时间相当长——在大块文本上进行文本处理,通常使用Python,而您所描述的内容在性能差异方面与我的经验完全不符。我经常读SSD。嗯,我做错了什么。keep getting ValueError:没有足够的值来解包(预期为2,得到0),通过删除文件名、搜索字符串=sys.argv[1:]使其正常工作。第一次测试非常棒。超快!
from multiprocessing import Process
valNotFound = True
def top():
    i=0
    while ValNotFound:
        i += 1


def bottom():
    ValNotFound = False


p1 = Process(target = top)
p2 = Process(target = bottom)
p1.start()
p2.start()