xrootd / xrootd-python

Python bindings for XRootD are now part of the main repository.
https://github.com/xrootd/xrootd
6 stars 8 forks source link

pyxrootd AttributeError #1

Closed jlsalmon closed 11 years ago

jlsalmon commented 11 years ago

moved from https://savannah.cern.ch/bugs/?101932

Dear Sir, I got the error when I was trying to download files by CopyProcess, do you know how to fix it? My OS: Scientific Linux CERN SLC release 6.4 (Carbon) My Python version:2.6.6 My xrootd version:3.3.2-1

Traceback (most recent call last): 
File "/usr/lib64/python2.6/site-packages/XRootD/client/copyprocess.py", line 30, in begin 
self.handler.begin(id, total, URL(source), URL(target)) 
AttributeError: 'NoneType' object has no attribute 'begin' 
Traceback (most recent call last): 
File "/usr/lib64/python2.6/site-packages/XRootD/client/copyprocess.py", line 36, in update 
self.handler.update(processed, total) 
AttributeError: 'NoneType' object has no attribute 'update' 
Traceback (most recent call last): 
File "/usr/lib64/python2.6/site-packages/XRootD/client/copyprocess.py", line 33, in end 
self.handler.end(XRootDStatus(status)) 
AttributeError: 'NoneType' object has no attribute 'end' 

Thanks for your help. Best Regards, W.J. Chang

jlsalmon commented 11 years ago

Hi WeiJen,

The CopyProcess class is supposed to be used with a corresponding CopyProgressHandler object, to receive updates about the progress of the copy jobs. This was introduced in version 1.1, but unfortunately the documentation for v1.1 has not been uploaded yet. But the progress handler is not compulsory, and indeed your code should not crash if you do not use one. So this is definitely a bug.

To fix your issue for now, you can subclass XRootD.client.utils.CopyProgressHandler like this:

from XRootD.client.utils import CopyProgressHandler

class ProgressHandler(CopyProgressHandler):
  """Utility class to handle progress updates from copy jobs"""

  def begin(self, id, total, source, target):
    """Notify when a new job is about to start

    :param     id: the job number of the copy job
    :param  total: total number of jobs being processed
    :param source: the source url of the current job
    :param target: the destination url of the current job
    """
    pass

  def end(self, status):
    """Notify when the previous job has finished

    :param status: status of the job
    """
    pass

  def update(self, processed, total):
    """Notify about the progress of the current job

    :param processed: bytes processed by the current job
    :param     total: total number of bytes to be processed by the current job
    """
    pass

and pass an instance of your progress handler to the copy process like this:

handler = ProgressHandler()
process.add_job(...) # 'process' is your CopyProcess object
process.prepare() 
process.run(handler=handler)

You can choose to do something useful with the progress handler if you wish, or just leave the methods empty.

Cheers, Justin

jlsalmon commented 11 years ago

FYI, the documentation has been updated and is available here.