【问题标题】:how do i keep closing a subthread from closing the stdin file descriptor?我如何继续关闭子线程而不关闭标准输入文件描述符?
【发布时间】:2018-08-12 15:18:58
【问题描述】:

我写了这段代码来澄清我的问题...我不断收到 ValueError: I/O operation on closed file。

没有从标准输入读取的子线程。在我启动子线程之前,循环运行良好......有人可以告诉我如何防止文件描述符关闭吗?

import threading
from threadtest2 import Threadtest
import termios, sys, tty
import time

def getchar():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch


tt2 = Threadtest()
stop = threading.Event()

t1 = threading.Thread(target=tt2.thread1, args=[stop, ])
t2 = threading.Thread(target=tt2.thread2, args=[stop, ])

try:
    while 1:
        while not stop.isSet():
            try:
                c = getchar()
            except IOError: pass
            if c == "q":
                stop.set()
            if c == "x":
                stop.set()
                exit()
            if c == "1":
                print "starting t1"
                t1.start()
            if c == "2":
                print "starting t2"
                t2.start()
        while len(threading.enumerate()) > 1:
            print 'waiting for ' + str(len(threading.enumerate()) - 1) + ' threads to close\r'
            time.sleep(1)
        stop.clear()
        print "stop has been triggered and reset... restart"
finally:
    print "done!"

还有一些其他线程(请原谅双关语)涉及到这一点,但我还没有找到一个直接解决这个问题的线程,并且已经有一段时间了。

仅供参考,子线程只是等待设置停止并休眠......

【问题讨论】:

    标签: python multithreading stdin


    【解决方案1】:

    我对您的代码进行了一些小改动以使其独立运行。以下内容不会在 Linux 机器上为我生成错误。你仍然看到它的错误吗?如果是这样,我很乐意改进答案 - 请提供更多关于您如何运行代码的详细信息,例如正在使用的操作系统。

    import threading
    import termios, sys, tty
    import time
    
    def getchar():
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
    
    class Threadtest:
        def thread1(self, stop):
            stop.wait()
            print "returning from thread1"
        def thread2(self, stop):
            stop.wait()
            print "returning from thread2"
    
    tt2 = Threadtest()
    stop = threading.Event()
    
    try:
        while 1:
            t1 = threading.Thread(target=tt2.thread1, args=[stop, ])
            t2 = threading.Thread(target=tt2.thread2, args=[stop, ])
    
            while not stop.isSet():
                try:
                    c = getchar()
                except IOError: pass
                if c == "q":
                    stop.set()
                if c == "x":
                    stop.set()
                    sys.exit()
                if c == "1":
                    print "starting t1"
                    t1.start()
                if c == "2":
                    print "starting t2"
                    t2.start()
            print "waiting for {} threads to close".format(threading.active_count() - 1)
            for t in [t1, t2]:
                t.join()
            stop.clear()
            print "stop has been triggered and reset... restart"
    finally:
        print "done!"
    

    【讨论】:

    • 这确实有效!但我无法弄清楚这在我的代码发生时如何不会产生错误。是允许它正常工作的连接语句吗?
    • 在 Python 中可能不需要连接。我添加它们以防万一。这只是在 C 中清理线程和分叉进程的习惯。我永远无法重现您看到的确切错误。我还移动了创建线程的位置,因此可以在按 Q 后启动新线程。
    猜你喜欢
    • 2012-04-29
    • 2012-02-23
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2013-02-22
    相关资源
    最近更新 更多