假设我有一个目录 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 包装文件并不理想,因为我正在发送标准输入并监听由 lisp 启动的 python 进程的标准输出。在 lisp 和评估输入文件的 python 进程之间添加另一个子进程意味着我需要做很多 stout/stdin 中继,我觉得这会很脆弱。
krzysz00 的方法效果很好。由于目录更改是在 lisp 中处理的,因此在启动 python 进程之前,这种方法将适用于启动不同子目录中的其他进程(不仅仅是 python)。
对于文档,这是我使用适用于 SBCL 和 CCL 的 krzsz00 方法的代码。请注意,它使用了 Hoyte 的 defmacro!来自Let Over Lambda的宏,可以轻松避免不需要的变量捕获:
#+: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))))
用法:
(with-cwd "./B"
(run-program ...))