当有多个生成器调用公共记录器时如何修复 python 记录顺序
How to fix the python logging order when there are multiple generators calling a common logger
有一个生成器列表 gen_list = [gen_1, gen_2, gen_3].
每个 gen_x 都有一个日志语句,将日志行放在一个公共日志文件中。
例如,
gen_1 放置日志行“log 1”
gen_2 放置日志行“log 2”
gen_3 放置日志行“log 3”
执行gen_list后,log_file如下所示。
日志 1
日志 2
日志 3
日志 3
日志 2
日志 1
日志 1
日志 2
日志 3
...
列表中生成器的执行顺序是交替的。 (1, 2, 3, 3, 2, 1, 1, 2, 3, ...)
有没有什么办法可以让命令总是向前的? (1, 2, 3, 1, 2, 3, 1, 2, 3, ...)
例如,我希望log_file是
日志 1
日志 2
日志 3
日志 1
日志 2
日志 3
...
您可以使用 zip()
来模拟遍历迭代器的循环,然后使用 itertools
中的 chain.from_iterable()
将 zip()
中的元组链接在一起。这允许您一次从一个生成器中读出一个元素。这种方法的一个显着优点是您可以使用任意多个生成器。
这是一个例子:
from itertools import chain
def gen_1():
for i in range(10):
yield "log1"
def gen_2():
for i in range(10):
yield "log2"
def gen_3():
for i in range(10):
yield "log3"
gen_list = [gen_1, gen_2, gen_3]
for elem in chain.from_iterable(zip(*[gen() for gen in gen_list])):
print(elem)
使用 zip()
后,您将生成如下内容:
[("log1", "log2", "log3"), ("log1", "log2", "log3"), ...]
然后,使用 chain.from_iterable()
展平这些元组,得到如下序列:
"log1", "log2", "log3", "log1", "log2", "log3", ...
我不确定您是否提供了所有信息来解释您的问题。这个脚本:
import logging
def gen_1():
for i in range(10):
logging.debug('log 1: %d' % i)
yield "log1"
def gen_2():
for i in range(10):
logging.debug('log 2: %d' % i)
yield "log2"
def gen_3():
for i in range(10):
logging.debug('log 3: %d' % i)
yield "log3"
gen_list = [gen_1(), gen_2(), gen_3()]
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
def main():
for i in range(10):
v = [next(gen_list[i]) for i in range(3)]
if __name__ == '__main__':
main()
打印,当运行(Python 3),
log 1: 0
log 2: 0
log 3: 0
log 1: 1
log 2: 1
log 3: 1
log 1: 2
log 2: 2
log 3: 2
log 1: 3
log 2: 3
log 3: 3
log 1: 4
log 2: 4
log 3: 4
log 1: 5
log 2: 5
log 3: 5
log 1: 6
log 2: 6
log 3: 6
log 1: 7
log 2: 7
log 3: 7
log 1: 8
log 2: 8
log 3: 8
log 1: 9
log 2: 9
log 3: 9
有一个生成器列表 gen_list = [gen_1, gen_2, gen_3].
每个 gen_x 都有一个日志语句,将日志行放在一个公共日志文件中。
例如,
gen_1 放置日志行“log 1”
gen_2 放置日志行“log 2”
gen_3 放置日志行“log 3”
执行gen_list后,log_file如下所示。
日志 1
日志 2
日志 3
日志 3
日志 2
日志 1
日志 1
日志 2
日志 3
...
列表中生成器的执行顺序是交替的。 (1, 2, 3, 3, 2, 1, 1, 2, 3, ...)
有没有什么办法可以让命令总是向前的? (1, 2, 3, 1, 2, 3, 1, 2, 3, ...)
例如,我希望log_file是
日志 1
日志 2
日志 3
日志 1
日志 2
日志 3
...
您可以使用 zip()
来模拟遍历迭代器的循环,然后使用 itertools
中的 chain.from_iterable()
将 zip()
中的元组链接在一起。这允许您一次从一个生成器中读出一个元素。这种方法的一个显着优点是您可以使用任意多个生成器。
这是一个例子:
from itertools import chain
def gen_1():
for i in range(10):
yield "log1"
def gen_2():
for i in range(10):
yield "log2"
def gen_3():
for i in range(10):
yield "log3"
gen_list = [gen_1, gen_2, gen_3]
for elem in chain.from_iterable(zip(*[gen() for gen in gen_list])):
print(elem)
使用 zip()
后,您将生成如下内容:
[("log1", "log2", "log3"), ("log1", "log2", "log3"), ...]
然后,使用 chain.from_iterable()
展平这些元组,得到如下序列:
"log1", "log2", "log3", "log1", "log2", "log3", ...
我不确定您是否提供了所有信息来解释您的问题。这个脚本:
import logging
def gen_1():
for i in range(10):
logging.debug('log 1: %d' % i)
yield "log1"
def gen_2():
for i in range(10):
logging.debug('log 2: %d' % i)
yield "log2"
def gen_3():
for i in range(10):
logging.debug('log 3: %d' % i)
yield "log3"
gen_list = [gen_1(), gen_2(), gen_3()]
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
def main():
for i in range(10):
v = [next(gen_list[i]) for i in range(3)]
if __name__ == '__main__':
main()
打印,当运行(Python 3),
log 1: 0
log 2: 0
log 3: 0
log 1: 1
log 2: 1
log 3: 1
log 1: 2
log 2: 2
log 3: 2
log 1: 3
log 2: 3
log 3: 3
log 1: 4
log 2: 4
log 3: 4
log 1: 5
log 2: 5
log 3: 5
log 1: 6
log 2: 6
log 3: 6
log 1: 7
log 2: 7
log 3: 7
log 1: 8
log 2: 8
log 3: 8
log 1: 9
log 2: 9
log 3: 9