子线程在python中并没有真正生成或者有一些问题?

2024-03-28 20:12:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从v$session中获取特定机器名的行,并生成一个子线程,该子线程调用一个名为kill_it()的函数来处理其特定行。主do_this()休眠100秒并检查更新的行。你知道吗

def do_this():

    sql='select * from v$session where machine like abc'
    session=Popen(['sqlplus','-S','/ as sysdba'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    session.stdin.write(sql)
    stdout,stderr=session.communicate()
    stdout=stdout.strip()
    stdout=stdout.split('\n')

    for i in range (len(stdout)):

        if 'no rows selected' not in stdout:
            sql_output=stdout[i].split(',')
            client_info=sql_output[0]
            sid=sql_output[1]
            serial=sql_output[2]
            program=sql_output[3]
            last_call=sql_output[4]
            process=sql_output[5]
            machine=sql_output[6]

            t = Thread(target=kill_it, args=(client_info,sid,serial,program,last_call,process,machine,))
            print t
            t.start()



while True:
    do_this()
    time.sleep(100)

但是在kill_it()函数中,它应该在自己的线程中运行,但是当我试图让子线程睡眠10秒时,它却在睡眠100秒,或者即使我删除了睡眠,它也不会一直在客户端信息中寻找xyz。你知道吗

def kill_it(client_info,sid,serial,program,last_call,process,machine):

    while True:
        print "thread is :"+str(current_thread())
        last_call=int(last_call)
        if 'xyz' in client_info and last_call>100 :
            command='alter system kill session \''+sid+','+serial+'\' immediate;'
            print command
            '''
            session=Popen(['sqlplus','-S','/ as sysdba'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
            session.stdin.write(command)
            stdout,stderr=session.communicate()
            print stdout
            print stderr
            '''

            print 'done'
            break;

        else:
            print 'Sleeping coz job didn`t run for more than 5mins'
            time.sleep(10)

当有一行但多于一行时,按预期工作。你知道吗


Tags: clientoutputsqlsessionstderrstdinstdoutit
1条回答
网友
1楼 · 发布于 2024-03-28 20:12:57

首先:

对于您的评论,您必须始终加入生成的线程和进程,以确保所有内容都被清除。如果这以一种侵入性的方式中断了程序的流程,那么您需要重新设计程序,因为出现了问题。您应该更仔细地了解Python多处理库,特别是multiprocessing.Pool()。你知道吗

其次:

请仔细查看do\u this()函数:

# stuff...
stdout=stdout.strip()
stdout=stdout.split('\n')

您可以使用菊花链字符串操作:

# stuff..
stdout=stdout.strip().split('\n')

现在开始你的循环。我不认为这是你真正想要的,它有几点你可以改进:

# the variable 'stdout' is now a tuple as returned by string.split('\n'), right?

# if you need a loop index, use enumerate() instead of this
for i in range (len(stdout)):

    # this if statement checks for membership in the tuple 'stdout' which is 
    # going to have the same result every time - did you mean to check the
    # elements of the tuple you're iterating over for something instead?
    if 'no rows selected' not in stdout: 

        # indexing into an iterable with a loop index is usually wrong in python 
        # not always, but usually
        sql_output=stdout[i].split(',') 

        # do you need to split this thing up into so many components when they're
        # all getting passed anyway?
        client_info=sql_output[0] 
        sid=sql_output[1]
        serial=sql_output[2]
        program=sql_output[3]
        last_call=sql_output[4]
        process=sql_output[5]
        machine=sql_output[6]

        t = Thread(target=kill_it, args=(client_info,sid,serial,program,last_call,process,machine,))
        print t
        t.start()
        # threads and processes should ALWAYS be joined

我建议将您的do\u this()代码重构为以下内容:

def do_this():

    sql='select * from v$session where machine like abc'
    session=Popen(['sqlplus','-S','/ as sysdba'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
    session.stdin.write(sql)
    stdout,stderr=session.communicate()
    stdout=stdout.strip().split('\n')

    if 'no rows selected' not in stdout:
        pool = multiprocessing.Pool()
        pool.map(kill_it, stdout) # blocking call until all are done
        pool.close()
        pool.join()

    return

pool.map()在传递给它的iterable中的每个对象上调用函数kill\u it,在本例中,它是分裂stdout得到的元组。如果您选择这样做,那么将由您决定将分隔逗号上的行的任务移到killïit函数中,并用一个参数替换长参数列表:要分割的字符串。你知道吗

TL;博士

我发现有两个问题可能会给您带来麻烦:
1始终加入线程和进程。如果不这样做,你可能会有奇怪的行为。
2检查do_this()for循环中的if语句。我不认为你真的想在那里检查整个stdout元组的'no rows selected',因为每次都是相同的结果,所以它应该在一个循环中。您可能正在删除/不删除您曾经/不打算删除的行。你知道吗

相关问题 更多 >