Interact with local & remote files by URI
pip install furi # Install basic support
pip install furi[aws] # Install AWS dependencies
pip install furi[sftp] # Install SFTP dependencies
import furi
with furi.open('/path/to/some/file.ext') as local:
print local.read()
# => Hello, world!
with furi.open('file:///path/to/local/file.ext') as local:
print local.read()
# => Hello from Local file system
If furi
was installed with AWS dependencies S3 files can be read as well:
with furi.open('s3://bucket/path/to/key') as s3:
print s3.read()
# => Hello from S3!
Same for SFTP files:
with furi.open('sftp://user:pass@host/path/to/file.ext') as sftp:
print sftp.read()
# => Hello from SFTP
# Walk S3 key
for dirpath, dirnames, filenames in furi.walk('s3://bucket/path/to/key/'):
print dirpath
print dirnames
print filenames
# Walk S3 with supplied credentials
credentials = {
'aws_access_key_id' : '<access_key>',
'aws_secret_access_key' : '<secret_key>' }
for dirpath, dirnames, filenames in furi.walk('s3://bucket/path/to/key/', **credentials):
print dirpath
print dirnames
print filenames
Example S3-file access:
# Using ~/.boto or ENV variables to authenticate
s3file = furi.open('s3://bucket/path/to/key')
# Supply credentials
s3file = furi.open('s3://bucket/path/to/key',
aws_access_key_id='ACCESS', aws_secret_access_key='SECRET' )
Supply the credentials as a part of the URI:
sftpfile = furi.open('sftp://user:password@host/workdir/file.ext')
Or with a key:
sftpfile = furi.open('sftp://user@host/workdir/file.ext', private_key='/path/to/ssh_id')
# Open a file in a supported open-mode
with furi.open('<uri>', mode='<mode>') as furifile:
furifile.exists() # Test if file exists
furifile.matches('regex pattern') # Match pattern to filename (not including path)
furifile.read() # Read file contents' stream as string
furifile.stream() # Get handle to file contents stream
furifile.write('str or stream') # Write a string or stream to file
furifile.connect(**credentials) # Connect to a remote file service (such as S3)
Structured JSON or YAML files can be loaded into a mapping object using the furi.map()
function.
Mapping local or S3-backed file contents operations are not cached so every read has some cost to it. If numerous reads are expected it is recommended that the object is mapped into a dictionary. File-based mapping objects do not support write operations at this time.
mymap = furi.map('s3://buket/path/to/mapping.json')
mymap = furi.map('/path/to/local/mapping.yaml')
print mymap['key']
# => "Hello, world!"
print mymap['otherkey'] # Reads file from S3 again
# => "Goodby, cruel world!"
# Reads the file once and caches it in `mymap`
mymap = dict(furi.map('s3://buket/path/to/mapping.json'))
Single partition-key DynamoDB tables without sort-keys are also supported and use the URI format "dynamodb://<tablename>/"
. The returned mapping object can be queried like a dictionary.
mynamo = furi.mapping('dynamodb://mytable/', region_name='us-east-1')
print mynamo['partition_key_value']
# => { "partition_key_name" : "partition_key_value",
# "field1": "Hello, world!",
# "field2": "Goodbye, cruel world!" }
It may be the case that you have a prioritized list of mapping files, where if a key cannot be found in the first map, the second is queried, then the third, and so on until a match is found or a KeyError
is thrown. Use the furi.chain()
function to chain mappings together.
chains = 's3://bucket/path/to/map.yml', '/path/to/local.json'
chainmap = furi.chain(*map(furi.map, chains))
print chainmap['key']
# => "Hello, world!"
print chainmap['otherkey']
# => WARNING:root:s3://bucket/path/to/map.yml :: KeyError('otherkey',)
# "Goodby, cruel world!"