Common Lisp:使用与 Lisp 进程不同的工作目录启动子进程

2023-12-12

假设我有一个目录 A 和子目录 B。我 cd 进入 A 并启动 lisp。在该 lisp 进程中,我想启动一个 Python 子进程,其中 Python 将 B 视为其当前工作目录。 lisp 进程需要在 A 中拥有 cwd,而 python 进程应该在 B 中拥有 cwd。我如何以跨平台、简单的方式做到这一点?

我正在寻找一种与 CCL 和 SBCL 一起使用的解决方案(可能使用“运行程序函数”),并且适用于 Windows、Linux 和 OS X。

我查看了 CCL 运行程序文档,没有找到更改启动进程的 cwd 的方法。

我查看了 Python 命令行参数,没有看到会更改 python 进程的 cwd 的参数。

我想到了运行程序调用“cd B;” python ...',但我不确定它是如何工作的,因为它实际上运行两个程序; cd,然后是 python。

Python 代码作为输入(作为文件)提供,因此我无法更改任何代码(通过添加 os.chdir() 调用或类似的调用)。

将 python 输入文件作为子进程启动的 python 包装文件并不理想,因为我正在发送 stdin 并监听由 lisp 启动的 python 进程的 stdout。在 lisp 和 python 进程之间添加另一个子进程来评估输入文件意味着我需要进行大量的 stout/stdin 中继,而且我感觉这会很脆弱。

krzysz00 的方法非常有效。由于目录更改是在 lisp 中处理的,因此在启动 python 进程之前,这种方法适用于在不同子目录(不仅仅是 python)中启动其他进程。

对于文档,这里是我的代码,使用适用于 SBCL 和 CCL 的 krzsz00 方法。请注意,它使用 Hoyte 的 defmacro!宏,从让拉姆达,轻松避免不需要的变量捕获:

#+:SBCL
(defun cwd (dir)
  (sb-posix:chdir dir))

(defun getcwd ()
  #+SBCL (sb-unix:posix-getcwd)
  #+CCL (current-directory))

(defmacro! with-cwd (dir &body body)
  `(let ((,g!cwd (getcwd)))
     (unwind-protect (progn
                       (cwd ,dir)
                       ,@body)
     (cwd ,g!cwd))))

Usage:

(with-cwd "./B"
  (run-program ...))

要运行外部程序(例如可移植的 python 进程),请参阅外部程序。要更改当前工作目录,请使用这个稍作修改的(公共域)函数cwd从文件中http://files.b9.com/lboot/utils.lisp,转载如下。

(defun cwd (&optional dir)
  "Change directory and set default pathname"
  (cond
   ((not (null dir))
    (when (and (typep dir 'logical-pathname)
           (translate-logical-pathname dir))
      (setq dir (translate-logical-pathname dir)))
    (when (stringp dir)
      (setq dir (parse-namestring dir)))
    #+allegro (excl:chdir dir)
    #+clisp (#+lisp=cl ext:cd #-lisp=cl lisp:cd dir)
    #+(or cmu scl) (setf (ext:default-directory) dir)
    #+cormanlisp (ccl:set-current-directory dir)
    #+(and mcl (not openmcl)) (ccl:set-mac-default-directory dir)
    #+openmcl (ccl:cwd dir)
    #+gcl (si:chdir dir)
    #+lispworks (hcl:change-directory dir)
    #+sbcl (sb-posix:chdir dir)
    (setq cl:*default-pathname-defaults* dir))
   (t
    (let ((dir
       #+allegro (excl:current-directory)
       #+clisp (#+lisp=cl ext:default-directory #-lisp=cl lisp:default-directory)
       #+(or cmu scl) (ext:default-directory)
       #+sbcl (sb-unix:posix-getcwd/)
       #+cormanlisp (ccl:get-current-directory)
       #+lispworks (hcl:get-working-directory)
       #+mcl (ccl:mac-default-directory)
       #-(or allegro clisp cmu scl cormanlisp mcl sbcl lispworks) (truename ".")))
      (when (stringp dir)
    (setq dir (parse-namestring dir)))
      dir))))

结合这两个函数,你想要的代码是:

(cwd #p"../b/")
(external-program:start "python" '("file.py") :output *pythins-stdout-stream* :input *pythons-stdin-stream*)
(cwd #p"../a/")

这会cd到 B,运行 python 进程,就像通过python file.py &,将 python 进程的 stdin/stdout 发送到指定的流(查看external-program文档以获取更多详细信息),最后执行另一个cwd将 lisp 进程返回给 A。如果 lisp 进程应该等到 python 进程完成,请使用external-program:run代替external-program:start.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Common Lisp:使用与 Lisp 进程不同的工作目录启动子进程 的相关文章

随机推荐

  • 如何在 Eclipse Juno/Kepler/Luna CDT 中启用 C++11?

    编辑 事实证明这确实不是 Eclipse Kepler 特有的 我必须对 Eclipse Juno 使用相同的过程 问题是 在回答同一问题的其他帖子中似乎缺少步骤 我正在使用 Eclipse Kepler for C 并尝试使用 C 11
  • 在 Linux 中混合使用 32 位和 64 位库 (gcc)

    我有一个为 Linux 使用 gcc 构建的 32 位纯二进制 C so 由供应商提供 我需要链接到 64 位 C C 应用程序 我正在开发 有什么方法可以从我的应用程序访问这个库吗 我知道需要小心处理 so 内部函数的参数和指针 而且我知
  • 如何将向量转换为Json对象? C++

    我有一个 RoomData 对象向量 这是该对象 typedef struct RoomData unsigned int id std string name std string maxPlayers unsigned int ques
  • setTimeout 循环。如何获得正确的订单

    我试图在循环中调用一个函数以实现不同的超时或延迟 for var i 0 i lt 10 i callDelayedFunction i function callDelayedFunction i setTimeout function
  • 将多个对象从 Angular 控制器发布到 Web API 2

    我能够从我的角度控制器发送一个原始 json 对象 该对象在我的 web api 方法中反序列化为已知类型 这很棒 但我现在需要能够在同一请求中发送其他参数 这些参数可以是 json 对象或简单类型 如 string 或 int 我看过类似
  • 同一域上的 CloudFront 静态网站和 EC2 API

    我的静态网站托管在 CloudFront 上 有没有办法让我使用相同的域名但不同的端口来调用 EC2 实例的 API Eg example com 3000应重定向到 EC2 实例 而example com aka example com
  • 通过隔行扫描加载图像 - 从低分辨率到全分辨率 - HTML

    我正在创建一个使用图像作为背景的网站 我讨厌从上到下加载图像 因为它只会使页面在加载时看起来很糟糕 我见过一些网站加载非常低分辨率的图像 然后逐渐提升到全分辨率照片 我希望我的网站也能这样做 但我不知道如何实现 这是否需要多个图像文件和更多
  • 从麦克风获取音频并将其写入 iOS 上的套接字

    这就是我想做的 从麦克风获取音频 采用 AAC G 711 或 G 726 编码 将编码帧写入套接字 我找到了很多例子 但它们都写入文件 您能否将我链接到任何具有输出缓冲区或回调的教程 文档 示例 库 我通过修改 Apple 的 Speak
  • 什么是 JAXB?为什么要使用它? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 这里有人发誓 JAXB 是自切片面包以来最伟大的东西 我很好奇 Stack Overflow 用户认为 JAXB 的用例是什么 以及是什么使它成为该用例的好或坏解决方案 我是用于操作 XM
  • JavaFX 和 Spring Boot - NPE

    我仍在与我的问题作斗争 我想使用 Spring Framework 来注入依赖项 并且必须使用 Spring boot 来集成两者 不幸的是 在第一个视图中 自动装配运行正确 但如果我进入下一个阶段 我仍然只能Null Pointer Ex
  • 是否可以检查对象是否已附加到实体框架中的数据上下文?

    当尝试附加已附加到给定上下文的对象时 我收到以下错误context AttachTo ObjectStateManager 中已存在具有相同键的对象 ObjectStateManager 无法跟踪具有相同键的多个对象 有没有一种方法可以实现
  • Xcode 4.4.1:git 不再显示修改

    不幸的是 突然间 我无法确定 Xcode 停止显示 git 信息的发生时刻 也无法从 Xcode 内部通过 git 提交 恢复 等 如果我检查组织者的存储库 我的项目仍会列出其上次提交 使用命令行 git status 我可以看到所有未暂存
  • PHP 中的 Session 和 Cookie 有什么区别?

    两者有什么区别Sessions and Cookies in PHP Cookie 是浏览器存储的一点数据 并随每个请求发送到服务器 会话是存储在服务器上并与给定用户关联的数据集合 通常通过包含 ID 代码的 cookie
  • 谷歌+登录,安卓登录时反复出现唱机提示

    我是安卓开发新手 我正在将 google plus 登录集成到我的应用程序中 我有点困惑谷歌的歌唱提示重复出现 我不明白为什么 我有什么问题吗 我正在关注谷歌开发者网站做这个东西 我使用多个谷歌帐户测试了该应用程序 但其中 2 个工作正常
  • 如何从 Scrapy 获取 UTF-8 编码的 unicode 输出?

    耐心听我说 我之所以写下每一个细节 是因为工具链的很多部分都不能很好地处理 Unicode 并且不清楚是什么原因导致的 PRELUDE 我们首先设置并使用最近的 Scrapy source scrapy 1 1 2 bin activate
  • 如何使用 iPhone sdk 将 XML 字符串转换为 JSON

    我正在实现一个基于客户端的应用程序 我有一个 xml 字符串 我需要将其转换为 JSON 格式并发送到服务器 我不知道如何转换这个 你们能给我建议任何文档或想法吗 步骤 1 将 XML 读入 NSDictionary http troybr
  • 在 Eclipse 中使用 -parameters 选项进行反射

    要使用 java 反射获取方法参数名称 我们必须使用 parameters 选项编译 Java 类 但是当我使用 VM Arguments 从 eclipse 中执行此操作时 我在控制台中收到以下错误 Unrecognized option
  • OpenCSVSerde escapeChar 覆盖 quoteChar

    我有许多 csv 文件正在导入到 Hive 中 并且我发现新行的 escapeChar 会被触发 即使它位于引用字段 即我的 quoteChar 内 有什么简单的方法可以解决这个困境吗 Line1field1 text Line1field
  • 是否可以在 div 区域中包含 box-shadow 来响应单击事件?

    我有一个div充当圆形按钮 它的设计使其整体外观的很大一部分来自于box shadow div style width 50px height 50px background yellow border none div 我有一个附加到按钮
  • Common Lisp:使用与 Lisp 进程不同的工作目录启动子进程

    假设我有一个目录 A 和子目录 B 我 cd 进入 A 并启动 lisp 在该 lisp 进程中 我想启动一个 Python 子进程 其中 Python 将 B 视为其当前工作目录 lisp 进程需要在 A 中拥有 cwd 而 python