可以't从Clojure repl运行(sh"python hello_world.py")



我有一个简单的Python文件hello.py,其中包含内容:print("Hello World"),当我尝试使用(sh "python3 hello.py")从REPL运行它时,我会得到

Execution error (IOException) at java.lang.UNIXProcess/forkAndExec (UNIXProcess.java:-2).
error=2, No such file or directory

显然,当我在shell中运行python3 hello.py时,程序就会运行。如何从Clojure repl运行Python文件?

将每个execve()元素(也就是说,在实际启动新进程时传递给操作系统的字符串数组中的每个元素(作为一个单独的参数:

(use '[clojure.java.shell :only [sh]])
(sh "python3" "hello.py")

与其名称可能暗示的相反,clojure.java.shell/sh实际上并没有调用sh。相反,它直接调用Runtime.exec(),后者接受一个直接的参数列表。

如果想要调用shell,可以显式地执行:

(use '[clojure.java.shell :only [sh]])
(sh "sh" "-c" "python3 hello.py")

或者,更好的做法是,使hello.py成为具有有效shebang的可执行文件,并直接调用它。也就是说,确保hello.py#!/usr/bin/env python3开始,运行chmod +x ./hello.py,并运行use:

(use '[clojure.java.shell :only [sh]])
(sh "./hello.py")

(此外,请考虑放弃.py扩展;就像您运行pip而不是pip.py,运行ls而不是ls.elf一样,可执行脚本也不应该有扩展(。

您可能对这个用于运行shell命令的辅助函数感兴趣

(shell-cmd <cmd-str>)

在默认操作系统shell(/bin/bash(中运行命令字符串;退货生成Clojure映射。示例:

(shell-cmd "ls -ldF *")

结果:

{:exit 0    ; unix exit status (0 -> normal) 
:err ''    ; text from any errors 
:out '...' ; text output as would printed to console 
}

首先尝试使用unix命令来帮助诊断任何PATH问题。


更新

查尔斯的回答是对的。当您通过shell/sh调用时,每个参数都需要一个不同的字符串。示例:

(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require
[tupelo.misc :as misc]
[clojure.java.shell :as shell] ))
(dotest
; `tupelo.misc/shell-cmd` calls bash first, so space is OK
(is= (misc/shell-cmd "python3 hello.py")
{:exit 0, :out "Hello Worldn", :err ""})
; calls `python3` directly. Need separate string "hello.py"
(is= (shell/sh "python3" "hello.py")
{:exit 0, :out "Hello Worldn", :err ""})
; fails since looking for a single command "python3 hello.py"
(throws? (shell/sh "python3 hello.py")))

相关内容

最新更新