26
26
import itertools
27
27
import scipy .stats as stats
28
28
29
- from .. import logging
29
+ from nipype import logging
30
30
31
- from . .interfaces .base import (BaseInterface , traits , TraitedSpec , File ,
31
+ from nipype .interfaces .base import (BaseInterface , traits , TraitedSpec , File ,
32
32
InputMultiPath , OutputMultiPath ,
33
33
BaseInterfaceInputSpec , isdefined ,
34
34
DynamicTraitedSpec )
35
- from . .utils .filemanip import fname_presuffix , split_filename
35
+ from nipype .utils .filemanip import fname_presuffix , split_filename
36
36
iflogger = logging .getLogger ('interface' )
37
37
38
38
@@ -1168,15 +1168,12 @@ class AddCSVRowOutputSpec(TraitedSpec):
1168
1168
class AddCSVRow (BaseInterface ):
1169
1169
"""Simple interface to add an extra row to a csv file
1170
1170
1171
- .. warning::
1171
+ .. note:: Requires `pandas <http://pandas.pydata.org/>`_
1172
1172
1173
- This interface is not thread-safe in multi-proc mode when
1174
- writing the output file.
1175
-
1176
-
1177
- .. note::
1178
-
1179
- Requires pandas - http://pandas.pydata.org/
1173
+ .. warning:: Multi-platform thread-safe execution is possible with
1174
+ `lockfile <https://pythonhosted.org/lockfile/lockfile.html>`_. Please recall that (1)
1175
+ this module is alpha software; and (2) it should be installed for thread-safe writing.
1176
+ If lockfile is not installed, then the interface is not thread-safe.
1180
1177
1181
1178
1182
1179
Example
@@ -1193,10 +1190,10 @@ class AddCSVRow(BaseInterface):
1193
1190
"""
1194
1191
input_spec = AddCSVRowInputSpec
1195
1192
output_spec = AddCSVRowOutputSpec
1193
+ _have_lock = False
1194
+ _lock = None
1196
1195
1197
1196
def __init__ (self , infields = None , force_run = True , ** kwargs ):
1198
- import warnings
1199
- warnings .warn ('AddCSVRow is not thread-safe in multi-processor execution' )
1200
1197
super (AddCSVRow , self ).__init__ (** kwargs )
1201
1198
undefined_traits = {}
1202
1199
self ._infields = infields
@@ -1217,6 +1214,15 @@ def _run_interface(self, runtime):
1217
1214
except ImportError :
1218
1215
raise ImportError ('This interface requires pandas (http://pandas.pydata.org/) to run.' )
1219
1216
1217
+ try :
1218
+ import lockfile as pl
1219
+ self ._have_lock = True
1220
+ except ImportError :
1221
+ import warnings
1222
+ warnings .warn (('Python module lockfile was not found: AddCSVRow will not be thread-safe '
1223
+ 'in multi-processor execution' ))
1224
+
1225
+
1220
1226
1221
1227
input_dict = {}
1222
1228
@@ -1230,13 +1236,22 @@ def _run_interface(self, runtime):
1230
1236
1231
1237
df = pd .DataFrame ([input_dict ])
1232
1238
1239
+ if self ._have_lock :
1240
+ self ._lock = pl .FileLock (self .inputs .in_file )
1241
+
1242
+ # Acquire lock
1243
+ self ._lock .acquire ()
1244
+
1233
1245
if op .exists (self .inputs .in_file ):
1234
1246
formerdf = pd .read_csv (self .inputs .in_file , index_col = 0 )
1235
1247
df = pd .concat ( [formerdf , df ], ignore_index = True )
1236
1248
1237
1249
with open (self .inputs .in_file , 'w' ) as f :
1238
1250
df .to_csv (f )
1239
1251
1252
+ if self ._have_lock :
1253
+ self ._lock .release ()
1254
+
1240
1255
return runtime
1241
1256
1242
1257
def _list_outputs (self ):
0 commit comments