如何使其与 Windows 兼容?

发布于 2024-09-14 05:22:37 字数 2195 浏览 2 评论 0原文

美好的一天,Stackoverflow!

我在将 Linux 的 Python 脚本之一移植到 Windows 时遇到了一个小(大)问题。令人毛骨悚然的是,我必须启动一个进程并将其所有流重定向到管道中,然后在脚本中对其进行读取和写入。

对于 Linux,这是小菜一碟:

server_startcmd = [
           "java", 
           "-Xmx%s" % self.java_heapmax, 
           "-Xms%s" % self.java_heapmin,
           "-jar",
           server_jar,
           "nogui"
        ]

server = Popen(server_startcmd, stdout = PIPE, 
                                stderr = PIPE, 
                                stdin  = PIPE)

outputs = [
     server_socket, # A listener socket that has been setup before
     server.stderr,
     server.stdout,
     sys.stdin # Because I also have to read and process this.
   ]

clients = []

while True:
     read_ready, write_ready, except_ready = select.select(outputs, [], [], 1.0)

     if read_ready == []:
        perform_idle_command() # important step
     else:
        for s in read_ready:
           if s == sys.stdin:
              # Do stdin stuff
           elif s == server_socket:
              # Accept client and add it to 'clients'
           elif s in clients:
              # Got data from one of the clients

服务器套接字、脚本的标准输入和子进程的输出通道(以及输入通道,因为我的脚本将写入该通道)之间的整个 3 路交替,尽管一个不在 select() 列表中)是脚本中最重要的部分。

我知道对于 Windows,win32api 模块中有 win32pipe。问题是找到这个 API 的资源非常困难,而且我找到的资源也没有太大帮助。

我如何利用这个 win32pipe 模块来完成我想要的事情?我有一些来源,它在不同但相似的情况下使用,但这让我很困惑:

if os.name == 'nt':
   import win32pipe
  (stdin, stdout) = win32pipe.popen4(" ".join(server_args))
else:
   server = Popen(server_args,
     stdout = PIPE,
     stdin = PIPE,
     stderr = PIPE)
   outputs = [server.stderr, server.stdout, sys.stdin]
   stdin = server.stdin

[...]

while True:
   try:
      if os.name == 'nt':
         outready = [stdout]
      else:
         outready, inready, exceptready = select.select(outputs, [], [], 1.0)
   except:
      break

stdout 这里是使用 win32pipe 启动的子进程的组合 stdout 和 stderr .popen4(...)

提出的问题是:

  • 为什么 Windows 版本不使用 select() 呢?那不行吗?
  • 如果您在那里不使用 select() ,我如何实现 select() 提供的必要超时(显然这里不会像这样工作)

请,帮帮我吧!

Good day, Stackoverflow!

I have a little (big) problem with porting one of my Python scripts for Linux to Windows. The hairy thing about this is that I have to start a process and redirect all of its streams into pipes that I go over and read and write to and from in my script.

With Linux this is a piece of cake:

server_startcmd = [
           "java", 
           "-Xmx%s" % self.java_heapmax, 
           "-Xms%s" % self.java_heapmin,
           "-jar",
           server_jar,
           "nogui"
        ]

server = Popen(server_startcmd, stdout = PIPE, 
                                stderr = PIPE, 
                                stdin  = PIPE)

outputs = [
     server_socket, # A listener socket that has been setup before
     server.stderr,
     server.stdout,
     sys.stdin # Because I also have to read and process this.
   ]

clients = []

while True:
     read_ready, write_ready, except_ready = select.select(outputs, [], [], 1.0)

     if read_ready == []:
        perform_idle_command() # important step
     else:
        for s in read_ready:
           if s == sys.stdin:
              # Do stdin stuff
           elif s == server_socket:
              # Accept client and add it to 'clients'
           elif s in clients:
              # Got data from one of the clients

The whole 3 way alternating between a server socket, stdin of the script and the output channels of the child process (as well as the input channel, as my script will write to that one, although that one is not in the select() list) is the most important part of the script.

I know that for Windows there is win32pipe in the win32api module. The problem is that finding resources to this API is pretty hard, and what I found was not really helpful.

How do I utilize this win32pipe module to do what I want? I have some sources where it's being used in a different but similar situation, but that confused me pretty much:

if os.name == 'nt':
   import win32pipe
  (stdin, stdout) = win32pipe.popen4(" ".join(server_args))
else:
   server = Popen(server_args,
     stdout = PIPE,
     stdin = PIPE,
     stderr = PIPE)
   outputs = [server.stderr, server.stdout, sys.stdin]
   stdin = server.stdin

[...]

while True:
   try:
      if os.name == 'nt':
         outready = [stdout]
      else:
         outready, inready, exceptready = select.select(outputs, [], [], 1.0)
   except:
      break

stdout here is the combined stdout and stderr of the child process that has been started with win32pipe.popen4(...)

The questions arsing are:

  • Why not select() for the windows version? Does that not work?
  • If you don't use select() there, how can I implement the neccessary timeout that select() provides (which obviously won't work like this here)

Please, help me out!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北城孤痞 2024-09-21 05:22:37

我认为你不能在管道上使用 select() 。
在其中一个项目中,我将 Linux 应用程序移植到 Windows,我也错过了这一点,不得不重写整个逻辑。

I think you cannot use select() on pipes.
In one of the projects, where I was porting a linux app to Windows I too had missed this point and had to rewrite the whole logic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文