管道的Swift任务打开文件描述符

时间:2018-10-24 17:47:23

标签: python objective-c swift macos

我正在尝试通过通过Swift Pipe执行的python脚本打开Swift Task

快捷代码

let pipe=Pipe()
let task = Process()
var env=ProcessInfo.processInfo.environment
task.launchPath = "/pythonscript.py"

let fh=pipe.fileHandleForWriting
task.arguments = ["\(fh.fileDescriptor)"]
task.launch()

Python

#!/usr/local/bin/python

import os
import sys

fd=int(sys.argv[1])
print(os.fdopen(fd, u'w'))

我从python脚本中得到的是

Traceback (most recent call last):
  File "./test.py", line 7, in <module>
    print(os.fdopen(fd, u'w'))
OSError: [Errno 9] Bad file descriptor

为什么python无法打开我在Swift中创建的文件描述符?

1 个答案:

答案 0 :(得分:0)

  

为什么python无法打开我在Swift中创建的文件描述符?

简短回答(有点困惑):因为文件描述符是一个进程本地标识符,操作系统使用它来链接到为进程保留的打开文件信息。您不能在进程之间复制它们。

长答案:

在macOS / Unix / Linux(* nix)中,文件描述符只是一个进程本地值,操作系统使用它来链接到操作系统中适当的打开文件信息。不同的进程可以具有完全相同的文件描述符值,这些值标识完全不同的文件。因此,您不能简单地在进程之间复制文件描述符值。

在* nix中,子进程从其父进程继承打开的文件及其关联的描述符。这是在进程之间传递文件描述符的唯一方法。概述中的步骤是:

  1. 父进程 forks ,创建其自身的副本
  2. 然后克隆将关闭孩子不应该访问的任何文件(通常是所有文件,标准输入,输出和错误文件除外)。
  3. 如果父母已经预打开了应该作为孩子的标准输入,输出或错误文件,则克隆会将这些文件的文件描述符重新分配给用于标准输入,输出和错误的标准文件描述符。
  4. 完成所有文件描述符工作后,克隆程序将其代码替换为子代需要运行的代码-这将保留打开的文件和文件描述符。
  5. 子代码现在不执行所有这些设置。

在Swift中,所有上述操作均由Process处理,在Terminal中,则由外壳程序处理,该外壳程序用于设置文件重定向,管道等。

要将管道连接到Python进程,您可以(a)使用Process方法将其附加到生成的进程的标准输入或输出上; (b)创建一个命名管道,该管道带有文件路径,并将该文件路径传递给python以打开;或(c)进行底层编程,并编写一些接口C代码,该代码会进行fork / dup(2) / exec调用,并使用已知描述符以外的管道启动Python代码标准输入或输出。

(a)最简单! (b)要求您对命名管道进行一些研究,这并不难,但是如果启用了沙箱,则需要使用沙箱,并且需要在两个进程都可以访问的目录中创建管道。 (c)最好避免。

玩得开心,如果您遇到麻烦,请提出一个新问题,以显示您尝试过的内容,出现问题的地方等。毫无疑问,有人会帮助您。

HTH