Python和sh中的多线程处理

2024-05-05 19:29:21 发布

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

我有一个shell脚本叫做“新罕布什尔州“它将本地网络中的ip地址和SSH放入该ip,然后从该ip连续读取一些数据并将结果附加到名为”日志.txt“在服务器上。在

我需要编写一个在服务器上运行的Python代码,它可能使用多线程在一个线程中运行此脚本,然后在另一个线程中读取文件中已有的值。”日志.txt". 我该怎么做?在

我写了以下代码:

#!/usr/bin/python
import threading
import time
from subprocess import call, Popen, PIPE

exitFlag = 0

class loggerThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print "Logging thread started ..."
    def run(self):
        with open("log.txt","at") as log: 
                call(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout = log)

class readerThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print "Reading thread started ..."
    def run(self):
        while 1:
                with open("log.txt","r") as log:
                        lines = log.read().split("\n")
                        print "Reader thread  ..."
                        print lines[-1]


thread1 = loggerThread()
thread2 = readerThread()

thread1.start()
thread2.start()

以下是“的内容”新罕布什尔州“:

^{pr2}$

但是,如果我运行此代码,则不会将任何内容存储在“日志.txt". 有什么办法解决这个问题吗?在


Tags: 代码importselfip服务器txt脚本log
3条回答

进程不必从Python多线程,而是从shell执行。将shell脚本放入一个函数中,并在另一个进程中附加一个与号(&;)来调用它。你找到PID就可以杀死它。然后迭代日志文件,并在写入日志文件时打印任何内容。在

试图通过这样的文件将信息从一个进程(或线程)流到另一个进程(或线程)是个坏主意。你必须让编写器确保在每一行之后刷新文件(而不是在中间行刷新文件),你必须同步,这样你只在有新数据要读取时才读取文件,而不是尽可能快地旋转,你必须弄清楚如何检测何时有新的数据要读取(这是特定于平台的),等等

这正是管道的用途。事实上,考虑到这条线:

from subprocess import call, Popen, PIPE

…我怀疑您复制并粘贴了一些使用管道执行操作的代码,否则,您为什么要导入PIPE?在

还有,我不知道你为什么认为你需要两条线。如果必须将输入发送到shell脚本并读取输出,那么使用两个线程可能会更容易。但您所要做的就是启动子进程,并在它可用时读取它的输出。所以只需从主线程的管道中读取。在

文档中有一些例子说明了如何做你想要的。在

^{pr2}$

迭代一个管道将会阻塞,直到另一行可用,然后读取整行,只要没有一行的长度超过select.PIPE_BUF(保证至少是512)。在


如果出于其他原因(例如,当这个线程收集输出时,您需要在主线程中执行一些其他工作),那么您可以使用与Python中任何其他线程完全相同的方法:创建一个threading.Thread子类,或者传递一个target函数。例如:

def nnsh():
    from subprocess import call, Popen, PIPE
    p = Popen(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout=PIPE)
    for line in p.stdout:
        print line
    p.wait()
t = threading.Thread(target=nnsh)
t.start()
# do a bunch of other stuff
t.join()

(当然,您可以让它成为一个守护线程,或者想出一种方法来通知它,而不是用无限的超时来连接它等等;如果您知道自己想要什么但不知道如何去做,请阅读一个基本教程或threading模块文档,如果您在某个地方卡住了,请另外发布一个新问题。)


如果在某些*nix平台上,您可能需要处理长得离谱的行(尽管在最新版本的OS X、FreeBSD、Linux或Solaris上似乎没有必要),那么您可能需要手动循环:

buf = ''
while True:
    buf += p.stdout.read(select.PIPE_BUF)
    lines = buf.split('\n')
    for line in lines[:-1]:
        print line
    buf = lines[-1]

这是@abarnert概念的变体。它运行着“新罕布什尔州“命令,然后按显示的方式处理每行数据。输出被写入sys.stdout,然后被刷新,这样我们就可以看到它来了,在结尾处看到它。在

来源

#!/usr/bin/env python

# adapted from http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line

import subprocess, sys, time

def test_ping():
    proc = subprocess.Popen(
        ['bash', './nn.sh', 'localhost', '3'],
        stdout=subprocess.PIPE,
    )
    outf = sys.stdout
    for line in iter(proc.stdout.readline, ''):
        outf.write( 'Reader thread ...\n' )
        outf.write( line.rstrip() + '\n' )
        outf.flush()

if __name__=='__main__':
    test_ping()

相关问题 更多 >