2012-04-06 6 views
4

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

私はCCLとSBCL(おそらく使用して「実行プログラム機能)で動作し、WindowsやLinuxのために働く、とOS Xのソリューションを探しています

私はCCL実行プログラムを見て私は、起動したプロセスのcwdを変更する方法を見ていませんでした。

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

「cd B」の実行プログラム呼び出しについて考えました。 python ... 'が、実際には2つのプログラムを実行しているので、どのように動作するのか分かりません。 cd、そしてpythonを実行します。

Pythonコードが入力として(ファイルとして)提供されているため、そのコードを変更することはできません(os.chdir()呼び出しを追加するなど)。

python入力ファイルをサブプロセスとして起動するpythonラッパーファイルは理想的ではありません。なぜなら私はstdinを送信し、lispによって起動されたpythonプロセスのstdoutを聞いているからです。 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 ...)) 

答えて

6

external-programを参照してください。現在の作業ディレクトリを変更するには、ファイルhttp://files.b9.com/lboot/utils.lispから若干修正した(パブリックドメイン)関数cwdを使用します。これは以下のとおりです。

この2つの機能を組み合わせる
(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)))) 

、あなたが欲しいのコードは次のとおりです。Bへ

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

この意志cdpython file.py &であるかのようにPythonのプロセスを実行し、指定にPythonのプロセスの標準入力/標準出力を送信ストリーム(詳細はexternal-programのドキュメントを参照)、最後にAにlispプロセスを返す別のcwdを実行します。Pythonプロセスが終了するまでlispプロセスが待機する必要がある場合は、external-program:startの代わりにexternal-program:runを使用します。

+0

素敵な提案;ありがとう。私は外部プログラムの互換性レイヤーを使用しませんでした。b/c私はsbclとcclに必要なのですが、それらの実行プログラムは基本的に同じですが、このコードのパッケージを簡単にロードできません。サーバー側で使用されていません。 –

+0

マルチスレッドプログラムには何か意味がありますか、またはスレッドごとに 'cwd'が変更されていますか? – Inaimathi

+0

私は 'cwd'が' thread_safety(5) 'の素早いスキムからスレッドごとだと思っていますが、完全にはわかりません。それが動作するかどうかを確認します。 – krzysz00

0

私はlispのが何であるかを知っているが、この作業は可能性がいけませんか? (移植性あなたのpythonのプロセスのような)外部プログラムを実行するには

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

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

+0

追加の制約を追加しました。 lispと最終的なpythonプロセスの間にpythonラッパープロセスを挿入するのは理想的ではありません。しかし、おそらく私はpythonラッパーファイルをロードするpythonプロセスを起動することができます。そのファイルはcdし、次にpythonの入力ファイルをロードしますか? –

+0

私は、これは非常に面倒な問題だと言わざるを得ない。 http://cybertiggyr.com/gene/pathnames-0/node11.html – apple16

+0

@Epic_orange:誰かが移植性層を書いてくれてありがとう。 – krzysz00

1

私はkrzysz00の提案を、hereというパッケージに書いてしまいました。

次に、UIOPには、getcwdchdirが含まれていると指摘しました。かなり最近のリスプをお持ちの場合は、asdfのエディションにUIOPが含まれているはずです。

関連する問題