cdo-bindings icon indicating copy to clipboard operation
cdo-bindings copied to clipboard

Cannot initialize with specified cdopath

Open barronh opened this issue 4 months ago • 1 comments

When cdo is not on the users path or when the cdo to be used is different, the version 1.6.0 will not work. This was not a problem with v1.5.x. To reproduce the error, look at the example failure section. The fix is surprisingly simple and is described in the resolution section.

Should I fork and make a PR?

Resolution

I think I have traced it down to differences between the Operator class.[1,2] In the new code, the init explicitly uses *args and **kwds, which are not provided. As a result, the cdo argument is lost to the child operators. This can be resolved by explicitly passing the CDO proprity as the argument to Operator.

580c580
<             setattr(self.__class__, method_name, Operator())
---
>             setattr(self.__class__, method_name, Operator(self.CDO))

[1] https://github.com/Try2Code/cdo-bindings/blob/master/python/cdo/cdo.py#L570-L581 [2] https://github.com/Try2Code/cdo-bindings/blob/maintenance-1.5.x/python/cdo.py#L608-L614

Example Failure

For example, I have a cdo binary at /usr/local/apps/cdo-2.2.1/intel-21.4/bin/cdo, which is not in my path.

which cdo
/usr/bin/which: no cdo in ...

But it is fully functional

/usr/local/apps/cdo-2.2.1/intel-21.4/bin/cdo sinfo -stdatm,0
cdo(1) stdatm: Process started
   File format : GRIB
    -1 : Institut Source   T Steptype Levels Num    Points Num Dtype : Parameter ID
     1 : unknown  unknown  c instant       1   1         1   1       : 1             
     2 : unknown  unknown  c instant       1   1         1   1       : 130.128       
   Grid coordinates :
     1 : lonlat                   : points=1 (1x1)
                              lon : 0 degrees_east
                              lat : 0 degrees_north
   Vertical coordinates :
     1 : height                   : levels=1
                            level : 0 m
   Time coordinate :
                             time : 1 step
     RefTime =  0000-00-00 00:00:00  Units = hours  Calendar = proleptic_gregorian
  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss  YYYY-MM-DD hh:mm:ss
  0001-01-01 00:00:00
cdo(1) stdatm: 
cdo    sinfo: Processed 2 variables over 1 timestep [0.00s 18MB]

If I use the python bindings with a specified, I get an error FileNotFoundError: [Errno 2] No such file or directory: 'cdo'

import cdo

cpath = '/usr/local/apps/cdo-2.2.1/intel-21.4/bin/cdo'
cdoo = cdo.Cdo(cpath)
f = cdoo.stdatm(0, returnCdf=True)

Error:

Traceback (most recent call last):
  File "/home/bhenders/temp/test_cdo.py", line 5, in <module>
    f = cdoo.stdatm(0, returnCdf=True)
  File "/home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py", line 580, in __getattr__
    setattr(self.__class__, method_name, Operator())
  File "/home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py", line 577, in __init__
    super().__init__(*args, **kwargs)
  File "/home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py", line 173, in __init__
    self.operators = self.__getOperators()
  File "/home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py", line 246, in __getOperators
    version = parse_version(getCdoVersion(self.CDO))
  File "/home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py", line 70, in getCdoVersion
    proc = subprocess.Popen(
  File "/usr/local/apps/oneapi/intelpython/python3.9/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/apps/oneapi/intelpython/python3.9/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'cdo'

Using pdb, I can go up to 580 line where self.CDO is as expected and calling Operator() raises the error.

> /home/bhenders/temp/cdopy/lib/python3.9/site-packages/cdo/cdo.py(580)__getattr__()
-> setattr(self.__class__, method_name, Operator())
(Pdb) self.CDO
'/usr/local/apps/cdo-2.2.1/intel-21.4/bin/cdo'
(Pdb) Operator()
*** FileNotFoundError: [Errno 2] No such file or directory: 'cdo'

barronh avatar Mar 20 '24 16:03 barronh