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

线程本地Python打印

线程本地Python打印,python,python-multithreading,Python,Python Multithreading,对于print()和类似内容,是否有任何内置方法使不同的线程具有不同的目标 我正在探索创建一个交互式Python环境,因此我不能只使用模块spamegg中的print()。它必须是无参数的全局可用线程。您可以用检查当前线程并写入相应文件的对象替换sys.stdout: import sys, threading class CustomOutput(object): def __init__(self): # the "softspace" slot is used i

对于
print()
和类似内容,是否有任何内置方法使不同的线程具有不同的目标


我正在探索创建一个交互式Python环境,因此我不能只使用模块spamegg中的
print()
。它必须是无参数的全局可用线程。

您可以用检查当前线程并写入相应文件的对象替换
sys.stdout

import sys, threading

class CustomOutput(object):
    def __init__(self):
        # the "softspace" slot is used internally by Python's print
        # to keep track of whether to prepend space to the
        # printed expression
        self.softspace = 0
        self._old_stdout = None

    def activate(self):
        self._old_stdout = sys.stdout
        sys.stdout = self

    def deactivate(self):
        sys.stdout = self._old_stdout
        self._old_stdout = None

    def write(self, s):
        # actually write to an open file obtained from an attribute
        # on the current thread
        threading.current_thread().open_file.write(s)

    def writelines(self, seq):
        for s in seq:
            self.write(s)

    def close(self):
        pass

    def flush(self):
        pass

    def isatty(self):
        return False

我可能会给你们一个解决方案,但这比打印要复杂得多

class ClusteredLogging(object):
    '''
    Class gathers all logs performed inside with statement and flush
    it to mainHandler on exit at once.
    Good for multithreaded applications that has to log several
    lines at once.
    '''


    def __init__(self, mainHandler, formatter):
        self.mainHandler = mainHandler
        self.formatter = formatter

        self.buffer = StringIO()
        self.handler = logging.StreamHandler(self.buffer)
        self.handler.setFormatter(formatter)


    def __enter__(self):
        rootLogger = logging.getLogger()
        rootLogger.addHandler(self.handler)


    def __exit__(self, t, value, tb):
        rootLogger = logging.getLogger()
        rootLogger.removeHandler(self.handler)
        self.handler.flush()
        self.buffer.flush()

        rootLogger.addHandler(self.mainHandler)
        logging.info(self.buffer.getvalue().strip())
        rootLogger.removeHandler(self.mainHandler)
使用此功能,您可以为每个线程创建日志处理程序,并将其配置为将日志存储到不同的位置

请记住,这是为了实现稍微不同的目标而开发的(请参阅注释),但您可以从ClusteredLogging的处理程序杂耍特性开始进行调整

还有一些测试代码:

import concurrent.futures
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO
import logging
import sys

# put ClusteredLogging here

if __name__ == "__main__":
    formatter = logging.Formatter('%(asctime)s %(levelname)8s\t%(message)s')
    onlyMessageFormatter = logging.Formatter("%(message)s")
    mainHandler = logging.StreamHandler(sys.stdout)
    mainHandler.setFormatter(onlyMessageFormatter)
    mainHandler.setLevel(logging.DEBUG)
    rootLogger = logging.getLogger()
    rootLogger.setLevel(logging.DEBUG)

    def logSomethingLong(label):
        with ClusteredLogging(mainHandler, formatter):
            for i in range(15):
                logging.info(label + " " + str(i))        

    labels = ("TEST", "EXPERIMENT", "TRIAL")

    executor = concurrent.futures.ProcessPoolExecutor()
    futures = [executor.submit(logSomethingLong, label) for label in labels]
    concurrent.futures.wait(futures)
你可以按你的要求去做,尽管它很复杂,很笨重,可能不便于携带,我不认为这是你想要做的

您对仅使用
spamegg.print
的异议是:

我正在探索创建一个交互式Python环境,因此我不能只使用模块
spamegg
中的
print()
。它必须是无参数的全局可用的

但解决方法很简单:只需在代码中使用module
spamegg
中的
print
,在交互式解释器中使用spamegg导入print。就这些

就这一点而言,没有充分的理由将其称为
print
。如果您的所有代码都使用了其他具有不同名称的输出函数,那么您可以在交互式解释器中执行相同的操作


但是如何让每个线程有不同的目的地呢

要做到这一点,最简单的方法就是在一个列表中查找目的地


但是如果你真的想用艰难的方式完成这两部分,你可以

要实现全局
打印
,您可以让
spamegg
替换内置的
打印
,而不只是给您一种阴影,或者让它替换
sys.stdout
,这样带有默认参数的内置
打印
将在其他地方打印

import builtins
_real_print = builtins.print
def _print(*args, **kwargs):
    kwargs.setdefault('file', my_output_destination)
    _real_print(*args, **kwargs)
builtins.print = _print

import io
import sys
class MyStdOut(io.TextIOBase):
    # ... __init__, write, etc.
sys.stdout = MyStdOut()
这仍然需要使用线程本地目标

或者,您可以在自己的自定义
globals
环境中编译或包装每个线程函数,该环境将替换默认的
\uuuuuuu内置函数和/或
sys
,允许您从一开始就为每个线程指定不同的函数。例如:

from functools import partial
from threading import Thread
from types import FunctionType

class MyThread(Thread):
    def __init__(self, group=None, target=None, *args, **kwargs):
        if target:
            g = target.__globals__.copy()
            g['__builtins__'] = g['__builtins__'].copy()
            output = make_output_for_new_thread()
            g['__builtins__']['print'] = partial(print, file=output)
            target = FunctionType(thread_func.__code__, g, thread_func.__name__, 
                                  thread_func.__defaults__, thread_func.__closure__)
        super().__init__(self, group, target, *args, **kwargs) 

你说的“无参数的全球可用的”是什么意思?全局可用的
print
函数接受0个或多个参数。您也可以轻松地定义另一个执行相同操作的
print
函数。(除非您使用的是Python2.x,而不是使用来自未来导入打印功能的
,在这种情况下,
print
首先不是一个函数,它是一种特殊的语句,您根本无法替换它。)同时,如果您想要不同的目的地,可以通过替换
sys.stdout
,来实现这一点,但这是一个全球性的
sys
,因此没有帮助。您几乎必须创建一些名称空间(可能是一个模块,但可能是一个假内置或
exec
上下文,或者在不了解更多设计的情况下,谁知道会发生什么…)其中包含
print
函数。@abarnert不使用
print(…,file=spamegg)
如果您对它的用处有任何评论,我将不胜感激。