4

ディレクトリ A とサブディレクトリ B があるとします。A に cd して Lisp を起動します。その Lisp プロセスで、Python が B を現在の作業ディレクトリと見なす Python サブプロセスを起動したいと思います。Lisp プロセスには A に cwd が必要であり、python プロセスには B に cwd が必要です。クロスプラットフォームで簡単な方法でこれを行うにはどうすればよいですか?

CCL と SBCL で動作し (おそらく 'run-program 関数を使用)、Windows、Linux、および OS X で動作するソリューションを探しています。

CCL 実行プログラムのドキュメントを見ましたが、起動されたプロセスの cwd を変更する方法がわかりませんでした。

Python コマンドライン引数を調べましたが、Python プロセスの cwd を変更するものは見当たりませんでした。

'cd B;' の実行プログラム呼び出しについて考えました。python ...' ですが、実際には 2 つのプログラムを実行しているため、それがどのように機能するかはわかりません。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 ...))
4

3 に答える 3

6

外部プログラム (移植可能な Python プロセスなど) を実行するには、external-programを参照してください。現在の作業ディレクトリを変更するには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))))

これら 2 つの関数を組み合わせると、必要なコードは次のようになります。

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

これはcdB に対して、python プロセスを by のように実行し、python file.py &python プロセスの stdin/stdout を指定されたストリームに送信し (詳細についてはexternal-programドキュメントを参照)、最後cwdに Lisp プロセスを A に返す別のプロセスを実行します。 Python プロセスが終了するまで待つ必要があります。external-program:run代わりにexternal-program:start.

于 2012-04-06T23:09:52.430 に答える
1

krzysz00 の提案をここにあるパッケージにまとめました。

その後、誰かがUIOPには と が付属しているgetcwdと指摘しましたchdir。かなり最近の Lisp をお持ちの場合は、UIOP が のエディションに含まれているはずですasdf

于 2014-03-20T22:38:57.000 に答える
0

私はlispが何であるかを知りませんが、これはうまくいくでしょうか?

  import subprocess
  subprocess.Popen('python myscript.py', cwd='B')

http://docs.python.org/library/subprocess.html

于 2012-04-06T21:26:27.457 に答える