请问我这样设置process环境变量的方法安全吗?

我的配置里有一些默认的环境变量,现在要启动一个新进程,希望新进程能使用一个新环境(增量在已有的环境)。

现在的做法是:

(let ((process-environment (cons "NAME=VALUE" process-environment)))
           (setq my-process (apply #'start-process "proc" (current-buffer) args)))

这么做确实有效果,而且letbinding之后的process-environment不会被污染。

但是emacs.stackexchange上有人说必须"create a copy of `process-environment` for the `let` -binding"?

请问我目前这种设置环境变量的方法安全吗?还是必须 copy?

多谢。

This function works by modifying process-environment.

As a special case, setting variable TZ calls set-time-zone-rule as
a side-effect.

from setenv

List of overridden environment variables for subprocesses to inherit.

Each element should be a string of the form ENVVARNAME=VALUE.

from process-environment

所以 process-environment 应该用 setenvgetenv 来操作,setenv 可能会对其进行有副作用的修改,所以建议先复制。

但是这个变量本身恰好是个 list,所以你用 cons 的方法有点歪门邪道,但是用 cons 的方法本身是无副作用的(不用复制备份)

1 个赞

Emacs 28 提供了一个新宏 with-environment-variables

(defmacro with-environment-variables (variables &rest body)
  "Set VARIABLES in the environment and execute BODY.
VARIABLES is a list of variable settings of the form (VAR VALUE),
where VAR is the name of the variable (a string) and VALUE
is its value (also a string).

The previous values will be be restored upon exit."
  (declare (indent 1) (debug (sexp body)))
  (unless (consp variables)
    (error "Invalid VARIABLES: %s" variables))
  `(let ((process-environment (copy-sequence process-environment)))
     ,@(mapcar (lambda (elem)
                 `(setenv ,(car elem) ,(cadr elem)))
               variables)
     ,@body))