# SoftBank Robotics documentation What's new in NAOqi 2.8?

# qicore.File

Import:

    import qi

    app = qi.Application()       # qi.Application must be instantiated first
    qicore = qi.module("qicore") # Load and import the qicore module

See qi.Module API and qi.Application API documentation for more details about importing modules.

Note: In the following code examples, this previous import code sample is assumed to prefix the example code. For a complete working example, see Complete example : Alice’s Image Store Service.

## Summary

`File` provides a way to open a file in read-only mode on the local file system and share the content of this file with potentially remote services.

We provide algorithms to copy a remote file’s content to make a local copy of it, using the `copyToLocal` function or `FileCopyToLocal` type.

## Reference

See qi::File C++ API for complete API reference.

## Detailed Usage Description

The following examples are partial for clarity. For a complete working example, see section Complete example : Alice’s Image Store Service.

### Opening a file in read-only mode for sharing access

Once qicore module is loaded, use `openLocalFile` to open the file in sharing read-only mode:

    file = qicore.openLocalFile("valid/path/to/file.ext")

In this example, the `file` object can be passed to a service API requesting a `File`, making the content of the file available to the service even if remote.

If the file does not exist, an exception will be thrown.

### File access lifetime

The lifetime of the file access is extended by the shared ownership between all the `File`, even if the instance is remote.

The `File` object is kept alive and the file access open by default until all `File` objects referring owning it are destroyed. The file access is automatically closed when `File` is destroyed.

Once you don’t need it anymore and want to explicitly stop owning the access, you can stop referencing the file access. The file access will be closed if there is no other owner still using it.

    def someServiceOperation(file):
        # Do some work  with file...

        # No need to work with the file anymore.
        del file # From now on, `file` is not usable anymore.
        # If we were the only one accessing this file,
        # access to it's content is now closed.

### Request or provide read-only access to the content of a file

A service can request read-only access to the content of a file by using `File` as argument.

Similarly, a service can provide read-only access to a file by having a function return a `File`.

For example (after loading qicore module):

    class MyService:
        #...

        # Store a copy of the provided file, associated with the provided name.
        def storeFile(fileToStore, name):
            #...

        # Provide access to a stored file found by name.
        def getFile(name):
            #...

        #...

(This is a partial example, see Complete example : Alice’s Image Store Service for complete working examples.)

In this example, the user of the service can provide access to a file this way:

    def backup(name, pathFileToStore):
        service = app.session.service('MyService')
        file = qicore.openLocalFile(pathFileToStore)
        # Now we can share reading access to this file.
        service.storeFile(file, name)
        # At this point, the service have a copy of the file and can start to work with it.

and acquire access to a file content provided by the service this way:

    def restore(name): # service is a MyService instance
        service = app.session.service('MyService')
        # Get Access to the file.
        file = service.getFile(name)

        if file:
          # Then work with the file content.
          # ...

### Make a local copy of a provided file

We can use the `copyToLocal` function to make a local copy of the file provided through a `File`. The `copyToLocal` function will transfer a copy of the content of the file to the local file system, even if the original file is on a remote file system.

For example, if we want a service function to make a full copy of a provided file, in a local temporary location, before doing any more work (after loading qicore module):

    class MyService:
        #...

        def storeFile(fileToStore, name): # fileToStore is a qicore.File instance

            # First, make a local copy in a temporary files directory:
            tempFilePath = generateTemporaryFilePath()
            qicore.copyToLocal(fileToStore, tempFilePath) # This call wait for the end of the copy.

            # We now have a local copy of the remote file,
            # we don't need the remote access anymore.
            fileToStore = None

            # Now we can work with the local copy of the file:
            storeFileInDatabase(name, tempFilePath)

In the same way, we can provide access to the data of the file by returning a `File`:

    class MyService:
        #...

        def getFile(name):

            fileLocation = findFileLocation(name)

            if os.path.isfile(fileLocation):
                # Now we can open it and provide it to the user for reading.
                return qicore.openLocalFile(fileLocation)

            # We didn't find the file!
            return None

Then the user can retrieve a copy of the file and work with it:

    def restore(service, name, fileLocation):

        # Get access to the file.
        file = service.getFile(name)

        if file: # The file was found.
            # We want to make a local copy before working on the file.
            qicore.copyToLocal(file, fileLocation)

            # We don't need the remote access anymore.
            del file

            # Now work on the file located at `fileLocation`.
            workOnFile(fileLocation)

### Observe the progression of a file copy, transfer or other long operations

Potentially long file operations like `copyToLocal` block until the end of the operation except if it is called with `_async=True` as parameter which will make the function return a qi.Future.

To wait for the end of the operation, we just wait for the future to be set (after loading qicore module):

    def printFinished():
        printf("File Transfer Finished!")

    def fetchFile(file): # file is a qicore.File instance

        temporaryFilePath = qi.makeTemporaryFilePath()

        # We copy the file on a temporary work location on the local filesystem,
        # but we don't wait for the transfer to end.
        transfer = qicore.copyToLocal(file, temporaryFilePath) # transfer is a qi.Future

        # We want to log the end of the transfer:
        transfer.then(printFinished)

        # Do some additional work while the file is transfered.
        someAdditionalWork()

        # Now we wait until the end of the operation if it's not finished yet.
        transfer.wait() # Don't wait for futures in real code, you should use .then() instead.
        del file
        del transfer

        workOnFile(temporaryFilePath)

(This is a partial example, see Complete example : Alice’s Image Store Service for complete working examples.)

In this example we want to be notified about the end of the operation, so we can connect a callback to the future. However, using only a future, we cannot get progress information about the transfer.

To get progress information and be able to connect callbacks to the different steps of the operation before the operation starts, we can use the `FileCopyToLocal` type instead of `copyToLocal` function:

    def printStatus(status): # see C++ API qi.FileOperation.Status for values
        if status == 2:                        # Status_Finished
            qi.info("File Transfer Finished!")
        elif status == 3:                      # Status_Failed
            qi.info("File Transfer Failed!")
        elif status == 4:                      # Status_Canceled
            qi.info("File Transfer Canceled!")

      # We ignore the other status.

    def printProgress(progress):
        qi.info("#### File Transfer Progress = {0}%".format(progressValue * 100) )

    def fetchFile(file): # file is a qicore.File instance
        temporaryFilePath = makeTemporaryFilePath()

        # Instead of launching the copy immediately, we prepare it by setting up
        # the object which represent that operation.
        fileCopy = qicore.FileCopyToLocal(file, temporaryFilePath)

        # We extract the progress notifier associated with the operation.
        notifier = fileCopy.notifier()

        # We want to log the state changes of the transfer.
        notifier.status.connect(printStatus)

        # We also to log the progress of the transfer.
        notifier.progress.connect(printProgress)

        # We are ready to launch the copy now.
        ft = fileCopy.start()

        # Do some additional work while the file is transfered.
        someAdditionalWork()

        # Now we wait until the end of the operation if it's not finished yet.
        ft.wait() # Don't wait for futures in real code, you should .connect()
                  # or its alternatives instead.

        # We don't need the file access anymore.
        del file

        workOnFile(temporaryFilePath)

The `FileCopyToLocal` type is an implementation of `FileOperation` which represents the copy/transfer operation which is not started upon creation. As this example demonstrates, the user can then plug callbacks to signals and properties provided by `ProgressNotifier` which is provided by the `FileOperation.notifier()` member function. The user can then start the copy operation by calling the `FileOperation.start()` member function.

Similarly, the side of the code which opened the file and provided access to it can also follow the progression of the on-going operations on the file by using the `File.operationProgress()` member function. This function provides access to a `ProgressNotifier` which is updated by the current file operation on the file.

    def printStatus(status) # as before
    def printProgress(progress) # as before

    def storeFile(service, name, pathToFileToStore):
        file = qicore.openLocalFile(pathToFileToStore)

        # Before sending the access to the file, connect progress logging callbacks.
        copyProgress = file.operationProgress()
        copyProgress.status.connect(printStatus)
        copyProgress.progress.connect(printProgress)

        # Now we can share reading access to this file.
        service.storeFile(file, name)

        # At this point, the service have a copy of the file and can start to work with it.

## Complete example : Alice’s Image Store Service

The following code samples are extracted from the complete example project located in the worktree at sdk/libqicore/libqicore/example/file/

In this example, Alice designs a service which provides storage for image files. Then Bob writes an application which accesses Alice’s image storage service and works with it.

### ImageStore

Alice’s ImageStore service is simple and straightforward. It is very similar to the example code in previous sections.

In particular:

Note the `File` usage which allows the user to provide access to a file, or to acquire a stored file access. See api-py-file-import for importing qicore module.

To implement the `store_image` function, Alice first acquires and copies the user file in a temporary location, then does some work to register it in the store’s database.

This is of course a simpler implementation, similar to the `get_image()` function implementation.

### ImageStore User Code

Meanwhile, Bob wrote his application to acquire Alice’s ImageStore instance, then do some basic work with it.

### Full Sources

imagestore.py:

file_example.py:

Glossary Site map Index Support Contact Legal Notices