Repository: nipy/nipype

Issue:
Issues of interfacing with PETPVC modules
Hi @effigies @alexsavio, I have run it in a Node and the content of the file report.rst as following:

Node: petpvc
============

 Hierarchy : pvc
 Exec ID : pvc

Original Inputs
---------------

* alpha : <undefined>
* args : <undefined>
* debug : False
* environ : {}
* fwhm_x : 2.0
* fwhm_y : 2.0
* fwhm_z : 2.0
* ignore_exception : False
* in_file : C:\Users\135173\Desktop\pvc_test\PET_nii\x_WB_CTAC_Body.nii.gz
* mask_file : C:\Users\135173\Desktop\pvc_test\mask_nill\skin_mask.nii.gz
* n_deconv : <undefined>
* n_iter : <undefined>
* out_file : C:\Users\135173\Desktop\pvc_test\pet_pvc_rbv.nii.gz
* pvc : RBV
* stop_crit : <undefined>
* terminal_output : stream

Thanks.



Discussion:
I don't see a problem with your environment. I wonder if you're not
escaping the back slashes in the file paths.

On Jun 6, 2017 11:54, "ubersexualShupeng" <notifications@github.com> wrote:

> Hi @effigies <https://github.com/effigies> @alexsavio
> <https://github.com/alexsavio>, I have run it in a Node and the content
> of the file report.rst as following:
> Node: petpvc
>
> Hierarchy : pvc
> Exec ID : pvc
> Original Inputs
>
>    - alpha :
>    - args :
>    - debug : False
>    - environ : {}
>    - fwhm_x : 2.0
>    - fwhm_y : 2.0
>    - fwhm_z : 2.0
>    - ignore_exception : False
>    - in_file : C:\Users\135173\Desktop\pvc_test\PET_nii\x_WB_CTAC_Body.
>    nii.gz
>    - mask_file : C:\Users\135173\Desktop\pvc_test\mask_nill\skin_mask.nii.
>    gz
>    - n_deconv :
>    - n_iter :
>    - out_file : C:\Users\135173\Desktop\pvc_test\pet_pvc_rbv.nii.gz
>    - pvc : RBV
>    - stop_crit :
>    - terminal_output : stream
>
> Thanks.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/nipy/nipype/issues/2068>, or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAFF8k0GOZhFXLcECocy2KO5litwNfSmks5sBXY-gaJpZM4NxjRB>
> .
>

I have tried to replace the back slashes to 'double back slashes' '\\' or forward dash '/' but the same error still appeared. Is there are any other possible problems?

The error messages as following:
TypeError: environment can only contain strings
Interface PETPVC failed to run. 

Thanks.
I believe nipype will pass your actual environment through. Can you check

```Python
import os
print(os.environ)
```

for non-string keys/values? (This may contain some personal information. If you're going to post the results of this for inspection, consider censoring it.)
@ubersexualShupeng are you still running into this issue?
Yes. I do not use this py module anymore. I use the PETPVC (binary) directly now. 
To be clear, are you able to run other external programs, such as FSL or FreeSurfer, through nipype, or is this `TypeError` specifically for PETPVC?

----

To get the context in this issue, the [code run](https://github.com/nipy/nipype/issues/1332#issuecomment-306476272) was:

```Python
import nipype
import nipype.interfaces.petpvc as PETPVC
pvc = PETPVC.PETPVC()
pvc.inputs.in_file = 'C:\Users\135173\Desktop\pvc_test\PET_nii\x_WB_CTAC_Body.nii.gz'
pvc.inputs.mask_file = 'C:\Users\135173\Desktop\pvc_test\mask_nill\skin_mask.nii.gz'
pvc.inputs.out_file = 'C:\Users\135173\Desktop\pvc_test\pet_pvc_rbv.nii.gz'
pvc.inputs.pvc = 'RBV'
pvc.inputs.fwhm_x = 2
pvc.inputs.fwhm_y = 2
pvc.inputs.fwhm_z = 2
outs = pvc.run()
```

With [error](https://github.com/nipy/nipype/issues/1332#issuecomment-306520880):

```Python
 Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Program Files\Anaconda2\lib\site-packages\nipype\interfaces\base.py", line 1081, in run
    runtime = self._run_wrapper(runtime)
  File "C:\Program Files\Anaconda2\lib\site-packages\nipype\interfaces\base.py", line 1724, in _run_wrapper
    runtime = self._run_interface(runtime)
  File "C:\Program Files\Anaconda2\lib\site-packages\nipype\interfaces\base.py", line 1755, in _run_interface
    redirect_x=self._redirect_x)
  File "C:\Program Files\Anaconda2\lib\site-packages\nipype\interfaces\base.py", line 1457, in run_command
    env=runtime.environ)
  File "C:\Program Files\Anaconda2\lib\subprocess.py", line 390, in __init__
    errread, errwrite)
  File "C:\Program Files\Anaconda2\lib\subprocess.py", line 640, in _execute_child
    startupinfo)
TypeError: environment can only contain strings
Interface PETPVC failed to run.
```

This may be a Unicode-on-Windows issue (see https://stackoverflow.com/questions/12253014/why-does-popen-fail-on-windows-if-the-env-parameter-contains-a-unicode-object).

I can see if I can make a patch that filters the environment for unicode strings and replaces them with `bytes`.

Resolving patch:
diff --git a/nipype/interfaces/base.py b/nipype/interfaces/base.py
--- a/nipype/interfaces/base.py
+++ b/nipype/interfaces/base.py
@@ -1381,6 +1381,35 @@ def _get_ram_mb(pid, pyfunc=False):
     return mem_mb
 
 
+def _canonicalize_env(env):
+    """Windows requires that environment be dicts with bytes as keys and values
+    This function converts any unicode entries for Windows only, returning the
+    dictionary untouched in other environments.
+
+    Parameters
+    ----------
+    env : dict
+        environment dictionary with unicode or bytes keys and values
+
+    Returns
+    -------
+    env : dict
+        Windows: environment dictionary with bytes keys and values
+        Other: untouched input ``env``
+    """
+    if os.name != 'nt':
+        return env
+
+    out_env = {}
+    for key, val in env:
+        if not isinstance(key, bytes):
+            key = key.encode('utf-8')
+        if not isinstance(val, bytes):
+            val = key.encode('utf-8')
+        out_env[key] = val
+    return out_env
+
+
 # Get max resources used for process
 def get_max_resources_used(pid, mem_mb, num_threads, pyfunc=False):
     """Function to get the RAM and threads usage of a process
@@ -1435,6 +1464,8 @@ def run_command(runtime, output=None, timeout=0.01, redirect_x=False):
             raise RuntimeError('Xvfb was not found, X redirection aborted')
         cmdline = 'xvfb-run -a ' + cmdline
 
+    env = _canonicalize_env(runtime.environ)
+
     default_encoding = locale.getdefaultlocale()[1]
     if default_encoding is None:
         default_encoding = 'UTF-8'
@@ -1449,14 +1480,14 @@ def run_command(runtime, output=None, timeout=0.01, redirect_x=False):
                                 stderr=stderr,
                                 shell=True,
                                 cwd=runtime.cwd,
-                                env=runtime.environ)
+                                env=env)
     else:
         proc = subprocess.Popen(cmdline,
                                 stdout=PIPE,
                                 stderr=PIPE,
                                 shell=True,
                                 cwd=runtime.cwd,
-                                env=runtime.environ)
+                                env=env)
     result = {}
     errfile = os.path.join(runtime.cwd, 'stderr.nipype')
     outfile = os.path.join(runtime.cwd, 'stdout.nipype')


Test patch: