Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用clj ftp在Clojure中重用ftp连接_Clojure_Ftp - Fatal编程技术网

使用clj ftp在Clojure中重用ftp连接

使用clj ftp在Clojure中重用ftp连接,clojure,ftp,Clojure,Ftp,我正在尝试使用Clojure从FTP服务器获取文件。我想使用一个连接下载所有文件。我正在使用clj ftp进行此操作。不幸的是,我无法通过一个连接实现它。有两个功能: (defn one-session [files] (ftp/with-ftp [client ftp-url] (map #(ftp/client-get client %1) files))) (defn get-all [files] (map #(ftp/with-ftp [client

我正在尝试使用Clojure从FTP服务器获取文件。我想使用一个连接下载所有文件。我正在使用clj ftp进行此操作。不幸的是,我无法通过一个连接实现它。有两个功能:

(defn one-session [files]
  (ftp/with-ftp [client ftp-url]
    (map #(ftp/client-get client %1)
         files)))

(defn get-all [files]
  (map #(ftp/with-ftp [client ftp-url]
          (ftp/client-get client %1))
       files))
调用
get all
时,一切正常。在尝试调用一个会话时,我得到了一个异常:NullPointerException org.apache.commons.net.SocketClient.getRemoteAddress(SocketClient.java:658)

我注意到在
cljftp
中有很多类型提示,它有影响吗

整个堆栈跟踪

Exception in thread "main" java.lang.NullPointerException, compiling:(/private/var/folders/4d/77tz4xfj7b1dkqtd3h4j10v40000gn/T/form-init2973639134882885374.clj:1:125)
    at clojure.lang.Compiler.load(Compiler.java:7391)
    at clojure.lang.Compiler.loadFile(Compiler.java:7317)
    at clojure.main$load_script.invokeStatic(main.clj:275)
    at clojure.main$init_opt.invokeStatic(main.clj:277)
    at clojure.main$init_opt.invoke(main.clj:277)
    at clojure.main$initialize.invokeStatic(main.clj:308)
    at clojure.main$null_opt.invokeStatic(main.clj:342)
    at clojure.main$null_opt.invoke(main.clj:339)
    at clojure.main$main.invokeStatic(main.clj:421)
    at clojure.main$main.doInvoke(main.clj:384)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)
    Caused by: java.lang.NullPointerException
    at org.apache.commons.net.SocketClient.getRemoteAddress(SocketClient.java:658)
    at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:789)
    at org.apache.commons.net.ftp.FTPClient._retrieveFile(FTPClient.java:1854)
    at org.apache.commons.net.ftp.FTPClient.retrieveFile(FTPClient.java:1845)
    at miner.ftp$client_get.invokeStatic(ftp.clj:144)
    at miner.ftp$client_get.invoke(ftp.clj:138)
    at miner.ftp$client_get.invokeStatic(ftp.clj:140)
    at miner.ftp$client_get.invoke(ftp.clj:138)
    at zephyr.fetch$one_session$fn__1296.invoke(fetch.clj:30)
    at clojure.core$map$fn__4785.invoke(core.clj:2644)
    at clojure.lang.LazySeq.sval(LazySeq.java:40)
    at clojure.lang.LazySeq.seq(LazySeq.java:49)
    at clojure.lang.RT.seq(RT.java:521)
    at clojure.core$seq__4357.invokeStatic(core.clj:137)
    at clojure.core$print_sequential.invokeStatic(core_print.clj:46)
    at clojure.core$fn__6072.invokeStatic(core_print.clj:153)
    at clojure.core$fn__6072.invoke(core_print.clj:153)
    at clojure.lang.MultiFn.invoke(MultiFn.java:233)
    at clojure.core$pr_on.invokeStatic(core.clj:3572)
    at clojure.core$pr.invokeStatic(core.clj:3575)
    at clojure.core$pr.invoke(core.clj:3575)

我已经检查了ftp库的源代码,似乎您必须了解由
map
创建的延迟序列。否则,当从结果序列中提取元素时,在离开
with ftp
块后执行对
ftp/client get
的调用,此时创建的连接已经关闭

要解决此问题,您需要使用以下方法强制实现序列:

这将强制所有
ftp/client get
调用在您的
with ftp
范围内发生

另一方面,可能不希望同时实现所有序列,因为它可能会产生危险的后果(例如内存使用)。您可能会阅读更多关于Clojure lazy seqs的文章,其中包含了一些副作用


在特定情况下,
ftp/client get
返回
boolean
值,指示文件下载到本地文件是否成功,因此这不是什么大问题。在其他情况下,您可能会重新设计API,以便您的函数不仅接受一系列文件,而且还接受一个函数,该函数封装了您希望对每个文件执行的操作,并将该函数应用于每个值,因为它一个接一个地被使用,而不会将整个序列保留在内存中@Frank Henard提出了一个有效的观点,您可以使用
doseq
来实现这一点。

您可以显示整个堆栈跟踪吗?我喜欢
doseq
用于副作用循环。在这样的组合中是否也可以使用
pmap
?我试着让它在2秒后挂起。还尝试了直接
future
调用,但内存不足。这取决于您使用的API是否是线程安全的。在这种情况下,您需要检查
FTPClient
是否可以从多个线程同时使用。
(defn one-session [files]
  (ftp/with-ftp [client ftp-url]
    (doall
      (map #(ftp/client-get client %1)
           files))))