Esri / ArcREST

python package for REST API (AGS, AGOL, webmap JSON, etc..)
Apache License 2.0
192 stars 155 forks source link

MapService exportTiles sample #171

Closed DShokes closed 8 years ago

DShokes commented 8 years ago

I'm muddling through trying to create a tpk from tiled basemaps. A sample showing non-Admin interactions with a public map services might clear up some confusion. However, I'm also having difficulty working with async jobs. For example,

estimate = MapService.estimateExportTilesSize(exportBy = 'LevelID', levels = '1-9', 
tilePackage = True, exportExtent = '-104,35.6,-94.32,41', 
areaOfInterest = None, async = True)

returns: {'jobStatus': 'esriJobSubmitted', 'jobId': 'j63eb1626d3bc4bc6abaa70d96480693a_et'} there does not appear to be any samples working with jobids or Map Service Jobs in general. So I set async=False.Then am able to run :

estimate['out_service_url'].asDictionary()

returning: {'dataType': 'GPString', 'value': {u'totalSize': 1547963, u'totalTilesToExport': 8}, 'paramName': None}

I can then check 'totalTilesToExport' and attempt to create a tpk. However, I get an error with exportTiles:

export = MapService.exportTiles( levels = '1-9', exportBy = 'LevelID', tilePackage = True,
exportExtent = '-104,35.6,-94.32,41', async = False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\ArcGIS10.3\lib\site-packages\arcrest\ags\mapservice.py", line 922, in exportTiles
    value = v['value']
TypeError: 'GPString' object has no attribute '__getitem__'

If exportTiles were to succeed, would the tpk be created in the default workspace automatically? This function doesn't require a destination like exporting a query to .gdb does. Thank you.

achapkowski commented 8 years ago

It would create a url

achapkowski commented 8 years ago

@DShokes Davin, is this on a mapservice through ArcGIS Server or ArcGIS Online? If arcgis server,what version are you using?

Thank you

DShokes commented 8 years ago

I'm using r"http://tiledbasemaps.arcgis.com/arcgis/rest/services/Reference/World_Transportation/MapServer" and I think I found the problem. I changed:

for k,v in results.items():
    if k == "out_service_url":
        value = v['value']

to

for k,v in results.items():
    if k == "out_service_url":
        value = v.value

and it works. v.asDictionary also works. Strangely, if I just print v on its own I get: TypeError: <bound method GPString.asDictionary of <arcrest.ags._gpobjects.GPString object at 0x0F09D2F0>> is not JSON serializable

DShokes commented 8 years ago

Here is the full test if it helps:

from arcrest.ags import mapservice as ms
from arcrest.ags import GPJob
from arcresthelper import securityhandlerhelper
import tempfile
securityinfo = {}
#securityinfo['security_type'] = 'Portal'
securityinfo['security_type'] = 'ArcGIS'
securityinfo['username'] = '***'
securityinfo['password'] = '***'
securityinfo['org_url'] = "http://www.arcgis.com"
securityinfo['proxy_url'] = None
securityinfo['proxy_port'] = None
securityinfo['token_url'] = None
securityinfo['certificatefile'] = None
securityinfo['keyfile'] = None
securityinfo['client_id'] = None
securityinfo['secret_id'] = None
securityinfo['referer_url'] = 'https://www.arcgis.com'

# the map service url
transportation_url = r"http://tiledbasemaps.arcgis.com/arcgis/rest/services/Reference/World_Transportation/MapServer"

shh = securityhandlerhelper.securityhandlerhelper(securityinfo=securityinfo)
ms_transport = ms.MapService(transportation_url,shh.securityhandler)

# define what the tiles to be exported
params = dict(exportBy = 'LevelID', levels = '1-9', 
    tilePackage = True, exportExtent = '-104,35.6,-94.32,41', 
    areaOfInterest = None)

# select the mode type
syncmode = False

# Get tile count
if ms_transport.exportTilesAllowed: # True
    estimate = ms_transport.estimateExportTilesSize(async = syncmode, **params)
    #{'jobStatus': 'esriJobSubmitted', 'jobId': 'j376dc2008fd3476a9394d729d3d06917_et'}
    if 'jobId' in estimate:
        jobId = estimate['jobId']
        jobUrl = "{}/jobs/{}".format(ms_transport.url,jobId)
        #'http://tiledbasemaps.arcgis.com/arcgis/rest/services/Reference/World_Transportation/MapServer/jobs/j376dc2008fd3476a9394d729d3d06917_et'
        gpJob = GPJob(url=jobUrl, securityHandler=shh.securityhandler)
        status = gpJob.jobStatus
        while status != "esriJobSucceeded":
            if status in ['esriJobFailed',
                          'esriJobCancelling',
                          'esriJobCancelled']:
                print gpJob.messages
                break
            else:
                print 'Status: {}'.format(status)
                time.sleep(5)
                status = gpJob.jobStatus
        results = gpJob.results #{'out_service_url': <arcrest.ags._gpobjects.GPString object at 0x0F09D2F0>}
    elif 'out_service_url' in estimate:
        results = estimate
    tilecount = 0
    if 'out_service_url' in results:
        tilecount = results['out_service_url'].asDictionary()['value']['totalTilesToExport']
    if 0 < tilecount < 100000:
        ms_transport.exportTiles(async=syncmode, **params)

when async is false: line 922, in exportTiles value = v['value'] TypeError: 'GPString' object has no attribute '__getitem__'

when async is true: {'error': {'message': 'Token Required', 'code': 499, 'details': []}}