Common Lisp的:启动子比口齿不清过程中的不同的工作目录 [英] Common Lisp: Launch subprocess with different working directory than lisp process

查看:211
本文介绍了Common Lisp的:启动子比口齿不清过程中的不同的工作目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假如我有一个目录,子目录和B.我CD插入和Lisp启动。在这个过程中口齿不清,我想推出一个Python子,其中Python看到乙方为其当前工作目录。 Lisp的过程中需要有CWD在A和蟒蛇的过程应该有B. CWD我如何做到这一点的一个跨平台的,简单的方法?

我在寻找与CCL和SBCL(可能使用运行程序功能)工作的解决方案,以及适用于Windows,Linux和OS X.

我看了一下CCL运行的程序文件,我没有看到一个方法来改变发射过程CWD。

我看了一下Python的命令行参数,我没有看到一个会改变蟒蛇过程CWD。

我想过一个运行程序调用的CD B:蟒蛇...',但我不知道如何将工作,因为它的真正运行两个程序; CD,然后蟒蛇。

Python的code是为作为输入(如文件),所以我不能(通过添加os.chdir()调用或类似)更改任何code的。

这是启动蟒蛇输入文件作为子蟒蛇封装文件并不理想,因为我送标准输入,并听取了LISP推出蟒蛇过程的标准输出。添加另一个子流程的LISP和evals输入文件意味着我需要做大量的粗壮/标准输入中继的蟒蛇过程之间,我有一种感觉,这将是易碎的。

krzysz00的做法效果很不错。由于目录变化在口齿不清处理,则推出了蟒蛇过程之前,这种方法用于启动在不同的子目录其它进程(不仅仅是Python)的工作。

有关的文件,这是一个使用krzsz00的做法,对SBCL和放大器的工作我code; CCL。注意,它使用霍伊特的defmacro!宏从让过LAMBDA ,轻松避免不必要的变量捕获:

 #+:SBCL
(CWD defun函数(DIR)
  (SB-POSIX:CHDIR DIR))(defun函数GETCWD()
  #+ SBCL(SB-UNIX:POSIX的GETCWD)
  #+ CCL(当前目录))(defmacro与-CWD(DIR功放&;!身体的身体)
  `(让((,G!CWD(GETCWD)))
     (放松保护(progn这个
                       (CWD,DIR)
                       ,@身体)
     (CWD,G!CWD))))

用法:

 (带-CWD./B
  (运行程序...))


解决方案

要(可移植喜欢你的Python程序)运行外部程序看到的外部计划。要改变当前工作目录,使用此略作修改(公共领域)函数 CWD 从文件中的 http://files.b9.com/lboot/utils.lisp ,这是下文。

 (CWD defun函数(安培;可选DIR)
  更改目录,并设置默认路径
  (条件
   ((没有(空目录))
    (当(和(typep DIR'逻辑路径)
           (翻译-逻辑路径DIR))
      (setq DIR(翻译-逻辑路径DIR)))
    (当(stringp DIR)
      (setq DIR(解析-namestring DIR)))
    #+快板(不包括:CHDIR DIR)
    #+ CLISP(#+口齿不清= CL分机:CD#-lisp = CL口齿不清:CD DIR)
    #+(或CMU SCL)(SETF(分机:默认目录)DIR)
    #+ cormanlisp(CCL:设置当前目录DIR)
    #+(和Mcl(不openmcl))(CCL:设置MAC-默认目录dir)
    #+ openmcl(CCL:CWD DIR)
    #+ GCL(SI:CHDIR DIR)
    #+ lispworks(HCL:变化目录dir)
    #+ SBCL(SB-POSIX:CHDIR DIR)
    (setq CL:*默认路径,默认* DIR))
   (T
    (让((DIR
       #+快板(不包括:当前目录)
       #+ CLISP(#+口齿不清= CL分机:默认目录#-lisp = CL口齿不清:默认目录)
       #+(或CMU SCL)(分机:默认目录)
       #+ SBCL(SB-UNIX:POSIX的GETCWD /)
       #+ cormanlisp(CCL:获取当前目录)
       #+ lispworks(HCL:获取工作目录)
       #+ MCL(CCL:MAC-默认目录)
       # - (或快板CLISP CMU SCL cormanlisp MCL SBCL lispworks)(。truename)))
      (当(stringp DIR)
    (setq DIR(解析-namestring DIR)))
      目录))))

结合这两个功能,你想要的code是:

 (CWD #P../ B /)
(外部程序:启动蟒蛇(file.py):输出* pythins-标准输出流*:输入*蟒蛇,标准输入流*)
(CWD #P../一/)

这将 CD 来B,运行过程蟒仿佛蟒蛇file.py&安培; ,送蟒蛇进程的标准输入/输出到指定的数据流(看外部程序文档了解更多信息),最后执行另一个 CWD 返回Lisp的过程A.如果口齿不清过程应该等到巨蟒过程结束后,使用外部程序:运行而不是外部程序:启动

Suppose I have a directory A, and subdirectory B. I cd into A and launch lisp. In that lisp process, I would like to launch a Python subprocess where Python sees B as its current working directory. The lisp process needs to have cwd in A, and the python process should have cwd in B. How do I do this in a cross-platform, simple way?

I'm looking for a solution that works with CCL and SBCL (probably using 'run-program function), and works for Windows, Linux, and OS X.

I looked at the CCL run-program documentation, and I didn't see a way to change the cwd of the launched process.

I looked at Python command-line arguments, and I didn't see one that would change the cwd of the python process.

I thought about a run-program call for 'cd B; python ...', but I'm not sure how that would work, since it's really running two programs; cd, and then python.

The Python code is being provided as input (as a file), so I cannot change any of that code (by adding an os.chdir() call or similar).

A python wrapper file that launches the python input file as a subprocess isn't ideal, because I'm sending stdin and listening to stdout of the python process launched by lisp. Adding another subprocess in between lisp and the python process that evals the input file means I'd need to do a lot of stout/stdin relaying, and I have a feeling that this would be brittle.

krzysz00's approach worked very well. Since the directory change is handled in lisp, before the python process is launched, this approach will work for launching other processes in different subdirectories (not just python).

For documentation, here's my code using krzsz00's approach that worked for SBCL & CCL. Note that it uses Hoyte's defmacro! macro, from Let Over Lambda, to easily avoid unwanted variable capture:

#+: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 ...))

解决方案

To run external programs (like your python process portably) see external-program. To change the current working directory, use this slightly modified (public domain) function cwd from the file http://files.b9.com/lboot/utils.lisp, which is reproduced below.

(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))))

Combining these two functions, the code you want is:

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

This will cd to B, run the python process as if by python file.py &, send the python process's stdin/stdout to the specified streams (look at the external-program documentation for more details), and finally execute another cwd that returns the lisp process to A. If the lisp process should wait until the python process is finished, use external-program:run instead of external-program:start.

这篇关于Common Lisp的:启动子比口齿不清过程中的不同的工作目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆