gpt4 book ai didi

python - 与长时间运行的 python 脚本交互

转载 作者:太空狗 更新时间:2023-10-30 01:29:00 25 4
gpt4 key购买 nike

我有一个长时间运行的 Python 脚本,它从 Twitter 收集推文,我想每隔一段时间就知道它是如何工作的。

目前,我正在使用 signal 库来捕捉中断,此时我调用我的打印函数。像这样:

import signal

def print_info(count):
print "#Tweets:", count

#Print out the process ID so I can interrupt it for info
print 'PID:', os.getpid()

#Start listening for interrupts
signal.signal(signal.SIGUSR1, functools.partial(print_info, tweet_count))

每当我需要我的信息时,我都会打开一个新终端并发出中断:

$kill -USR1 <pid>

有更好的方法吗?我知道我可以在预定的时间间隔内执行脚本,但我更感兴趣的是按需了解,并可能发出其他命令。

最佳答案

向进程发送信号会中断进程。您将在下面找到一种使用专用线程来模拟 python 控制台的方法。控制台作为 unix 套接字公开。

import traceback
import importlib
from code import InteractiveConsole
import sys
import socket
import os
import threading
from logging import getLogger

# template used to generate file name
SOCK_FILE_TEMPLATE = '%(dir)s/%(prefix)s-%(pid)d.socket'

log = getLogger(__name__)


class SocketConsole(object):
'''
Ported form :eventlet.backdoor.SocketConsole:.
'''
def __init__(self, locals, conn, banner=None): # pylint: diable=W0622
self.locals = locals
self.desc = _fileobject(conn)
self.banner = banner
self.saved = None

def switch(self):
self.saved = sys.stdin, sys.stderr, sys.stdout
sys.stdin = sys.stdout = sys.stderr = self.desc

def switch_out(self):
sys.stdin, sys.stderr, sys.stdout = self.saved

def finalize(self):
self.desc = None

def _run(self):
try:
console = InteractiveConsole(self.locals)
# __builtins__ may either be the __builtin__ module or
# __builtin__.__dict__ in the latter case typing
# locals() at the backdoor prompt spews out lots of
# useless stuff
import __builtin__
console.locals["__builtins__"] = __builtin__
console.interact(banner=self.banner)
except SystemExit: # raised by quit()
sys.exc_clear()
finally:
self.switch_out()
self.finalize()


class _fileobject(socket._fileobject):
def write(self, data):
self._sock.sendall(data)

def isatty(self):
return True

def flush(self):
pass

def readline(self, *a):
return socket._fileobject.readline(self, *a).replace("\r\n", "\n")


def make_threaded_backdoor(prefix=None):
'''
:return: started daemon thread running :main_loop:
'''
socket_file_name = _get_filename(prefix)

db_thread = threading.Thread(target=main_loop, args=(socket_file_name,))
db_thread.setDaemon(True)
db_thread.start()
return db_thread


def _get_filename(prefix):
return SOCK_FILE_TEMPLATE % {
'dir': '/var/run',
'prefix': prefix,
'pid': os.getpid(),
}


def main_loop(socket_filename):
try:
log.debug('Binding backdoor socket to %s', socket_filename)
check_socket(socket_filename)

sockobj = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sockobj.bind(socket_filename)
sockobj.listen(5)
except Exception, e:
log.exception('Failed to init backdoor socket %s', e)
return

while True:
conn = None
try:
conn, _ = sockobj.accept()
console = SocketConsole(locals=None, conn=conn, banner=None)
console.switch()
console._run()
except IOError:
log.debug('IOError closing connection')
finally:
if conn:
conn.close()


def check_socket(socket_filename):
try:
os.unlink(socket_filename)
except OSError:
if os.path.exists(socket_filename):
raise

示例程序:

make_threaded_backdoor(prefix='test')
while True:
pass

示例 session :

mmatczuk@cactus:~$ rlwrap nc -U /var/run/test-3196.socket
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import os
>>> os.getpid()
3196
>>> quit()
mmatczuk@cactus:~$

这是一个非常强大的工具,可用于:

  • 转储线程,
  • 检查进程内存,
  • 按需附加调试器,pydev debugger (适用于 eclipse 和 pycharm),
  • 强制 GC,
  • 动态定义 monkeypatch 函数

甚至更多。

关于python - 与长时间运行的 python 脚本交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24276204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com