当前位置: 首页 > 知识库问答 >
问题:

PyObc作为通过管道与主进程通信的子进程不起作用

谷梁宁
2023-03-14

我试图发送信号从我的pyObc gui(osx状态栏中的菜单)到我的应用程序的主进程。具体来说,我在一个类中运行gui,在一个进程中运行this,我试图通过管道将消息从gui发送到主进程。

当我使用一种简单的方法将数据放入管道中时,我的代码可以工作。消息被传递到主进程,产生main进程。。。recv():foo当我在子流程中启动gui并尝试将数据放入管道时,比如当我单击菜单选项“开始”时,什么都不会发生。主流程线从未打印,据我所知,主流程被阻塞。

我假设这与pyobjc中的事件循环有关。我能做些什么来让它工作?如何将pyobjc代码作为子进程运行?

main.py

import sys
from multiprocessing import Process, Pipe
from userinterface import OSXstatusbaritem

def f2(pipe):
    print "starting subprocess f2"
    print pipe.send("foo")
    pipe.close()

def main():
    pipeUI, pipeServer = Pipe()

    # p = Process(target=f2, args=(pipeUI,)) # <---------------------- This works
    p = Process(target=OSXstatusbaritem.start(pipeUI), args=()) # <----This doesn't

    p.start()
    print "main process... recv():", pipeServer.recv()
    p.join()

if __name__ == "__main__": sys.exit(main())

用户界面。派克

import objc, re, os
from Foundation import *
from AppKit import *
from PyObjCTools import AppHelper
from multiprocessing import Pipe

status_images = {'idle':'./ghost.png'}

class OSXstatusbaritem(NSObject):
    images = {}
    statusbar = None
    state = 'idle'

    @classmethod
    def start(self, pipe):
        self.pipe = pipe
        self.start_time = NSDate.date()
        app = NSApplication.sharedApplication()
        delegate = self.alloc().init()
        app.setDelegate_(delegate)
        AppHelper.runEventLoop()

    def applicationDidFinishLaunching_(self, notification):
        statusbar = NSStatusBar.systemStatusBar()
        # Create the statusbar item
        self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
        # Load all images
        for i in status_images.keys():
            self.images[i] = NSImage.alloc().initByReferencingFile_(status_images[i])
        # Set initial image
        self.statusitem.setImage_(self.images['idle'])
        # self.statusitem.setAlternateImage_(self.images['highlight'])
        # Let it highlight upon clicking
        self.statusitem.setHighlightMode_(1)
        # Set a tooltip
        self.statusitem.setToolTip_('Sample app')

        # Build a very simple menu
        self.menu = NSMenu.alloc().init()
        # Start and stop service
        menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Start Service', 'startService:', '')
        self.menu.addItem_(menuitem)
        menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Stop Service', 'stopService:', '')
        self.menu.addItem_(menuitem)
        # Add a separator
        menuitem = NSMenuItem.separatorItem()
        self.menu.addItem_(menuitem)
        # Terminate event
        menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_('Quit', 'terminate:', '')
        self.menu.addItem_(menuitem)
        # Bind it to the status item
        self.statusitem.setMenu_(self.menu)

        # Get the timer going
        self.timer = NSTimer.alloc().initWithFireDate_interval_target_selector_userInfo_repeats_(self.start_time, 5.0, self, 'tick:', None, True)
        NSRunLoop.currentRunLoop().addTimer_forMode_(self.timer, NSDefaultRunLoopMode)
        self.timer.fire()

    def tick_(self, notification):
        print self.state

    def startService_(self, notification):
        self.pipe.send(["foobar", None])
        print "starting service"

    def stopService_(self, notification):

        print "stopping service"

共有1个答案

哈襦宗
2023-03-14

您的代码在主进程(main.py)中创建GUI对象,然后在使用fork创建的子进程中使用该对象。苹果的大多数框架都不支持这一点。

此外,还需要调用OSXstatusbaritem。start在主进程中创建并运行eventloop。

通过在子进程中创建GUI对象,您可能会获得更大的成功,但即使这样也不能保证工作(如果您运气不好,GUI框架已经初始化,并且在子进程中使用时导致崩溃):

p = Process(target=OSXstatusbaritem.start, args=(pipeUI,))

启动状态栏项process的最安全方法是使用subprocess,以避免在不调用execv(2)的情况下创建新流程。在Python的tracker上,有人讨论过向多处理模块添加一个选项,以使用fork-exec启动新的进程,但这还没有导致提交。

 类似资料:
  • remote模块是一种渲染器进程(网页)和主进程之间通信(IPC)的简单方法。 进程: 渲染进程​ 在Electron中,GUI相关模块(例如 dialog, menu等)只能用在主进程而非渲染器进程中使用。 为了从渲染器进程使用它们, ipc模块是向主进程发送进程间消息所必需的。 remote模块可以调用主进程对象的方法,而类似于Java的RMI无需显式地发送进程间消息。 从渲染器进程创建浏览器

  • 我试图与一个进程通信(该进程本身会写入stdin和stdout,以便在终端中与用户交互),并在C中读取它的stdin和写入它的stdout。 因此,我尝试以编程方式替换shell用户。一个methapohrical示例:假设出于某种原因我想在C中使用VIM。然后我还需要编写命令(stdout)并从编辑器(stdin)中读取内容。 起初我认为这可能是一项微不足道的任务,但似乎没有标准的方法<代码>i

  • Process 结构体代表了一个正在运行的子进程,并公开了stdin(标准输入),stdout(标准输出) 和 stderr(标准错误) 句柄,通过管道和底层的进程交互。(原文:The Process struct represents a running child process, and exposes the stdin, stdout and stderr handles for int

  • 进程间通信(Inter-Process Communication),简称IPC。 分类 管道通信 信号通信 共享内存通信* 信号量通信* 消息队列通信* 套接口(Socket)通信 全双工管道通信(部分Unix系统支持,Linux只支持半双工管道) 加星号*的三种通信方式,是源自于AT&T发行的System V(SYSV)版本的新IPC机制。 管道 管道pipe 命名管道FIFO FIFO 命名

  • 问题内容: 我试图在Linux机器上使用Subversion,存储库位于Microsoft sbs2008服务器上。(我可以从Microsoft Windows 7计算机访问存储库。)有人可以告诉我如何使其工作吗? 这就是我所做的。 strace显示: 问题答案: 不要通过网络共享来安装Subversion存储库,否则它将无法可靠地运行。 file://访问仅适用于本地单用户访问,尤其是测试和调试

  • 从渲染进程到主进程的异步通信 进程: 渲染进程​ ipcRenderer模块是EventEmitter类的一个实例。 它提供了几个方法,所以你可以从渲染进程(网页)发送同步和异步消息到主进程。您还可以从主流程接收回复。 事件方法 ipcRenderer.on(channel, listener) 用途:监听 channel,并调用 listener(event, args...) 处理新消息 ch