最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

XIO: fatal IO error 0 (Success) on X server ":0" Kivy multiprocessing - Stack Overflow

programmeradmin1浏览0评论

Hi I am trying to create a program that when run, two windows open at the same time, from the same app. For this multihtreading is needed, but it seems I get some strange errors:

XIO:  fatal IO error 0 (Success) on X server ":0"
      after 187 requests (187 known processed) with 24 events remaining.
[xcb] Unknown sequence number while processing queue
[xcb] You called XInitThreads, this is not your fault
[xcb] Aborting, sorry about that.
python: xcb_io.c:278: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.

for now this is just a test implementation, copying two of the same windows, for simplicity. In the future two different windows' for different purposes will be done.

I will send my full code I am working with because strangely, a simpler version with same exact structure works:

from multiprocessing import Process
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label

KV = '''
BoxLayout:
    orientation: 'vertical'

    Label:
        text: "This is a window"
'''

class MainApp(App):
    def build(self):
        return Builder.load_string(KV)

def run_app():
    MainApp().run()

if __name__ == '__main__':
    processes = [Process(target=run_app) for _ in range(2)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

my code now:

from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.card import MDCard
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDButton, MDIconButton
from kivymd.uix.relativelayout import MDRelativeLayout
from kivymd.uix.boxlayout import MDBoxLayout
from multiprocessing import Process


class OrderCard(MDCard):
    _card_count = 0
    
    def __init__(self, **kwargs):
        OrderCard._card_count += 1
        super().__init__(
            padding="8dp",
            size_hint=(1, None),
            height="100dp",
            **kwargs
        )
        
        layout = MDRelativeLayout()
        
        label = MDLabel(
            text=f"Order Added {OrderCard._card_count}",
            adaptive_size=True,
            text_color="grey",
            pos_hint={"center_y": 0.5, "center_x": 0.5},
            bold=True
        )
        layout.add_widget(label)
        
        buttons_layout = MDBoxLayout(
            orientation='horizontal',
            size_hint=(None, None),
            width="96dp",
            height="48dp",
            pos_hint={"top": 1, "right": 1},
            spacing="4dp"
        )
        
        edit_btn = MDIconButton(
            icon="square-edit-outline",
            on_press=self.edit_card,
            size=("24dp", "24dp")
        )
        delete_btn = MDIconButton(
            icon="trash-can-outline",
            on_press=self.delete_card,
            size=("24dp", "24dp")
        )
        
        buttons_layout.add_widget(edit_btn)
        buttons_layout.add_widget(delete_btn)
        layout.add_widget(buttons_layout)
        
        self.add_widget(layout)

    def delete_card(self, *args):
        parent = self.parent
        parent.remove_widget(self)

    def edit_card(self, *args):
        print("Entered menu")

class MainScreen(MDScreen):
    def add_order(self):
        stack = self.ids.stack
        stack.add_widget(OrderCard(size_hint_y=None))

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Light"
        self.theme_cls.primary_palette = "Moccasin"
        return MainScreen()
    
def run_app():
    MainApp().run()

if __name__ == '__main__':
    processes = [Process(target=run_app) for _ in range(2)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

main.kv:

<MainScreen>:
    md_bg_color: self.theme_cls.backgroundColor  
    BoxLayout:
        padding: "10sp"
        ScrollView:
            do_scroll_x: False
            do_scroll_y: True
            StackLayout:
                on_children:
                    if self.parent.scroll_y == 0.0: self.parent.scroll_y = 0.00000001
                size_hint_y: None
                height: self.minimum_height
                spacing: "15sp"
                padding: "20sp"    
                id: stack
        BoxLayout:
            orientation: 'vertical'
            padding: "20sp"
            width: "160dp"
            size_hint_x: None
            MDButton:
                spacing: "10sp"
                style: "elevated"
                size: "100sp", "70sp"
                size_hint: None,None
                on_release: root.add_order()
                MDButtonIcon:
                    icon: "plus"
                MDButtonText:
                    id: order_btn
                    text: "Add Order"
                    theme_font_size: "Custom"
                    font_size: "15sp"
            Widget:

Tried removing anything related to KivyMD library and use pure Kivy instead, but with no success. Expected seeing two windows launch at the same time when the python program is run.

Hi I am trying to create a program that when run, two windows open at the same time, from the same app. For this multihtreading is needed, but it seems I get some strange errors:

XIO:  fatal IO error 0 (Success) on X server ":0"
      after 187 requests (187 known processed) with 24 events remaining.
[xcb] Unknown sequence number while processing queue
[xcb] You called XInitThreads, this is not your fault
[xcb] Aborting, sorry about that.
python: xcb_io.c:278: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.

for now this is just a test implementation, copying two of the same windows, for simplicity. In the future two different windows' for different purposes will be done.

I will send my full code I am working with because strangely, a simpler version with same exact structure works:

from multiprocessing import Process
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label

KV = '''
BoxLayout:
    orientation: 'vertical'

    Label:
        text: "This is a window"
'''

class MainApp(App):
    def build(self):
        return Builder.load_string(KV)

def run_app():
    MainApp().run()

if __name__ == '__main__':
    processes = [Process(target=run_app) for _ in range(2)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

my code now:

from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.card import MDCard
from kivymd.uix.label import MDLabel
from kivymd.uix.button import MDButton, MDIconButton
from kivymd.uix.relativelayout import MDRelativeLayout
from kivymd.uix.boxlayout import MDBoxLayout
from multiprocessing import Process


class OrderCard(MDCard):
    _card_count = 0
    
    def __init__(self, **kwargs):
        OrderCard._card_count += 1
        super().__init__(
            padding="8dp",
            size_hint=(1, None),
            height="100dp",
            **kwargs
        )
        
        layout = MDRelativeLayout()
        
        label = MDLabel(
            text=f"Order Added {OrderCard._card_count}",
            adaptive_size=True,
            text_color="grey",
            pos_hint={"center_y": 0.5, "center_x": 0.5},
            bold=True
        )
        layout.add_widget(label)
        
        buttons_layout = MDBoxLayout(
            orientation='horizontal',
            size_hint=(None, None),
            width="96dp",
            height="48dp",
            pos_hint={"top": 1, "right": 1},
            spacing="4dp"
        )
        
        edit_btn = MDIconButton(
            icon="square-edit-outline",
            on_press=self.edit_card,
            size=("24dp", "24dp")
        )
        delete_btn = MDIconButton(
            icon="trash-can-outline",
            on_press=self.delete_card,
            size=("24dp", "24dp")
        )
        
        buttons_layout.add_widget(edit_btn)
        buttons_layout.add_widget(delete_btn)
        layout.add_widget(buttons_layout)
        
        self.add_widget(layout)

    def delete_card(self, *args):
        parent = self.parent
        parent.remove_widget(self)

    def edit_card(self, *args):
        print("Entered menu")

class MainScreen(MDScreen):
    def add_order(self):
        stack = self.ids.stack
        stack.add_widget(OrderCard(size_hint_y=None))

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Light"
        self.theme_cls.primary_palette = "Moccasin"
        return MainScreen()
    
def run_app():
    MainApp().run()

if __name__ == '__main__':
    processes = [Process(target=run_app) for _ in range(2)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

main.kv:

<MainScreen>:
    md_bg_color: self.theme_cls.backgroundColor  
    BoxLayout:
        padding: "10sp"
        ScrollView:
            do_scroll_x: False
            do_scroll_y: True
            StackLayout:
                on_children:
                    if self.parent.scroll_y == 0.0: self.parent.scroll_y = 0.00000001
                size_hint_y: None
                height: self.minimum_height
                spacing: "15sp"
                padding: "20sp"    
                id: stack
        BoxLayout:
            orientation: 'vertical'
            padding: "20sp"
            width: "160dp"
            size_hint_x: None
            MDButton:
                spacing: "10sp"
                style: "elevated"
                size: "100sp", "70sp"
                size_hint: None,None
                on_release: root.add_order()
                MDButtonIcon:
                    icon: "plus"
                MDButtonText:
                    id: order_btn
                    text: "Add Order"
                    theme_font_size: "Custom"
                    font_size: "15sp"
            Widget:

Tried removing anything related to KivyMD library and use pure Kivy instead, but with no success. Expected seeing two windows launch at the same time when the python program is run.

Share Improve this question asked yesterday George RăbușGeorge Răbuș 32 bronze badges New contributor George Răbuș is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct. 0
Add a comment  | 

1 Answer 1

Reset to default 0

I am not sure exactly why your approach does not work. However, keep in mind that when using multiprocessing, your code may get loaded several times by the initial process. That may lead to issues, including multiple executions of some of your code. Those issues are difficult to diagnose, since the Process class doesn't provide any convenient way to access stderr or stdout. I suggest using the subprocess module instead. Here is a modification of your if __name__ == '__main__': code block that I think accomplishes what you want:

if __name__ == '__main__':
    if len(sys.argv) == 1:
        # this is the normal situation
        for _ in range(2):
            # run this python script in a subprocess that will continue after this process exits
            if sys.platform == 'linux':
                subprocess.Popen([sys.executable, sys.argv[0], 'dummy_arg'],  # add an additional arg as a flag
                     stdout=subprocess.DEVNULL,
                     stderr=subprocess.DEVNULL,
                     preexec_fn=os.setpgrp)
            elif sys.platform == 'win32':
                subprocess.Popen([sys.executable, sys.argv[0], 'dummy_arg'],  # add an additional arg as a flag
                     stdout=subprocess.DEVNULL,
                     stderr=subprocess.DEVNULL,
                     creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NO_WINDOW)
            else:
                print('no match for platform')
    else:
        # this happens when there is an additional arg (arg is unused)
        print('starting actual app')
        run_app()

The above code uses the subprocess.Popen() for each desired instance of the App. The normal execution of the code will produce the subprocess executions, but adds a dummy arg. That dummy arg forces the execution of the else: code block, which just runs the App.

There are different arguments to the Popen call for different platforms to create a subprocess that continues to run after the calling process exits. The linux code block runs exactly as you want (for me). The win32 code starts the desired Apps, but also opens another window for each instance of the App. I haven't found a way to eliminate those extra windows.

发布评论

评论列表(0)

  1. 暂无评论