Hi @Neil47 ,
I'm wondering if you will get consistent output running the following code (mashed up between your code and some stuff I run on a consistent basis, hoping I got it all right if you put in your tokenkey). This code will just try getting the enrollments list, and then print the length (number of enrollments found). I'd expect it to give the same result each time you run it (assuming you're not constantly changing the enrollments in the course.
Without seeing your output, I'd guess possibly a pagination issue or some kind of request error is happening based on my own experience. I was running into a lot of random errors in out test environment in the last few weeks, so I had to add the retry method found in my script below (googled to find that, I'm by no means a python expert). Even though it uses slightly more memory, my scripts all use the canvas_get_allpages function just to avoid recreating the same request loops over and over. I think I've accounted for all of the possible responses and headers for pagination in that function now, and I've gotten reliable results in all the calls I do lately with these improvements. Someone else might come in and offer some way better advice, but I thought I'd take a stab since I've been tinkering more with python lately.
-Chris
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import json
from datetime import datetime
import csv
# Requests call with retry on server error
def requestswithretry(retries=3, backoff_factor=0.3, status_forcelist=(500, 502, 504), session=None, ):
session = session or requests.Session()
retry = Retry(
total=retries,
read=retries,
connect=retries,
backoff_factor=backoff_factor,
status_forcelist=status_forcelist,
allowed_methods=frozenset({'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE', 'POST'})
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session
# Paginated API call to Canvas
# returns list of dictionary objects from json
def canvas_get_allpages(url, headers):
if not 'per_page=' in url:
if '?' in url:
url=url+'&per_page=100'
else:
url=url+'?per_page=100'
rl=[] #list of JSON items converted to python dictionaries
repeat=True
while repeat:
r=requestswithretry().get(url,headers=headers)
if r.status_code!=200:
print(datetime.now().isoformat()+': Error',r.status_code,'while retrieving get response from ',url)
repeat=False
else:
rj=r.json()
if type(rj) is dict:
for key in rj:
rl=rl+rj[key]
else:
rl=rl+rj
url=r.links.get('current',{}).get('url',url)
last_url=r.links.get('last',{}).get('url','')
if (url != last_url) and ('next' in r.links.keys()):
url=r.links['next']['url']
else:
repeat=False
return rl
course_id=3010
BASE_URL=f"https://companyname.org/api/v1/courses/{course_id}/enrollments"
TOKEN={'Authorization': 'Bearer tokenkey'}
enrollments_list=canvas_get_allpages(BASE_URL,TOKEN)
print(len(enrollments_list))
This discussion post is outdated and has been archived. Please use the Community question forums and official documentation for the most current and accurate information.