Install & Compatibility
Where this runs
tested against v1.2.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.647s · 24.7MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 2.4s · import 0.557s · 25MB
23MB installed
● package 23MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
ServiceNowClient
✓ from pysnc import ServiceNowClient
✗ import pysnc
The primary synchronous client for interacting with ServiceNow.
AsyncServiceNowClient
✓ from pysnc.asyncio import AsyncServiceNowClient
Used for asynchronous operations, requires `pysnc[asyncio]` installation.
ServiceNowPasswordGrantFlow
✓ from pysnc.oauth2 import ServiceNowPasswordGrantFlow
One of several OAuth2 authentication flows available, alongside ClientCredentialsGrantFlow.
This quickstart demonstrates how to initialize the `ServiceNowClient` using environment variables for credentials, create a `GlideRecord` object, add a query, execute it, and iterate through the results. It also shows how to fetch a single record by its `sys_id`.
import os
from pysnc import ServiceNowClient
# Configure environment variables for secure access
SN_INSTANCE = os.environ.get('SN_INSTANCE', 'your_instance.service-now.com')
SN_USERNAME = os.environ.get('SN_USERNAME', 'your_username')
SN_PASSWORD = os.environ.get('SN_PASSWORD', 'your_password')
if not all([SN_INSTANCE, SN_USERNAME, SN_PASSWORD]):
print("Please set SN_INSTANCE, SN_USERNAME, and SN_PASSWORD environment variables.")
exit(1)
try:
# Initialize the ServiceNow client with basic authentication
client = ServiceNowClient(SN_INSTANCE, (SN_USERNAME, SN_PASSWORD))
# Create a GlideRecord object for the 'incident' table
gr = client.GlideRecord('incident')
# Add a query condition (e.g., active incidents)
gr.add_query('active', 'true')
gr.add_limit(5) # Limit results for demonstration
# Execute the query
gr.query()
# Iterate through the results (Pythonic iteration is recommended)
print(f"Found {gr.get_row_count()} active incidents:")
for record in gr:
print(f" Incident Number: {record.number}, Short Description: {record.short_description}")
# Example of getting a single record by sys_id
if gr.get_row_count() > 0:
first_sys_id = gr.next().sys_id # Using .next() here for specific record access
single_record = client.GlideRecord('incident')
if single_record.get(first_sys_id):
print(f"\nRetrieved single incident: {single_record.number}")
except Exception as e:
print(f"An error occurred: {e}")
Debug
Known issues
gotchaWhen iterating a `GlideRecord` using the traditional `gr.next()` method, you must call `gr.rewind()` if you wish to iterate a second time over the same result set. Pythonic iteration (e.g., `for record in gr:`) handles this automatically and is generally preferred.fixUse `for record in gr:` for iteration. If using `gr.next()`, call `gr.rewind()` before re-iterating.
affects: All versions
gotchaFor optimal performance, explicitly set `GlideRecord.fields` to retrieve only the necessary columns and tune `batch_size` based on your instance's configuration and API usage. Retrieving all fields or very large batches can impact performance.fixBefore `gr.query()`, set `gr.fields = 'field1,field2,sys_id'`. Adjust `client.GlideRecord('table', batch_size=X)` as needed. affects: All versions
breakingVersions prior to 1.1.9 contained a bug where `GlideRecord.changes()` could incorrectly return `False` when multiple modifications were made to a record, leading to missed updates or incorrect state detection.fixUpgrade `pysnc` to version 1.1.9 or later to ensure `GlideRecord.changes()` functions correctly.
affects: <1.1.9
gotchaUnlike ServiceNow's native JavaScript APIs which use camelCase (e.g., `addQuery`), `pysnc` adheres to Python's PEP 8 guidelines, using snake_case for method names (e.g., `add_query`). Using incorrect casing will result in `AttributeError`.fixAlways use snake_case for `pysnc` method calls, such as `gr.add_query()`, `gr.get_value()`, `gr.update_multiple()`.
affects: All versions
breakingUsers of `pip >= 24` experienced installation or runtime issues with older versions of `pysnc` due to dependency resolution changes. This was addressed in `pysnc` 1.1.7.fixEnsure you are using `pysnc` version 1.1.7 or newer.
affects: <1.1.7 with pip >= 24
gotchaWhen using `GlideRecord.update_multiple()`, setting field values directly as properties (e.g., `gr.state = '10'`) can lead to unintended updates across all records in the table. Always use `gr.set_value('field_name', 'new_value')` for field assignments before calling `update_multiple()` to ensure only queried records are affected.fixReplace `gr.field = 'value'` with `gr.set_value('field', 'value')` when preparing for `update_multiple()` operations. affects: All versions
Errors
Common errors & fixes
AttributeError: 'GlideRecord' object has no attribute 'addQuery'
Attempting to use camelCase method names (like in ServiceNow JavaScript) instead of Pythonic snake_case.
fixChange method calls to snake_case, e.g., `gr.add_query()` instead of `gr.addQuery()`, `gr.get_value()` instead of `gr.getValue()`.
TypeError: 'NoneType' object has no attribute 'GlideRecord' or 'NoneType' object is not callable
The `ServiceNowClient` object failed to initialize or authenticate, returning `None` or an invalid object, then subsequent calls fail.
fixVerify the ServiceNow instance URL (`SN_INSTANCE`) and ensure that authentication credentials (username/password or OAuth details) are correct and that the user has the necessary API roles. Check for network connectivity issues.
RuntimeWarning: 'GlideRecord' object is not rewindable. Iteration can only occur once.
A `GlideRecord` object that was initialized with `rewindable=False` (or after `gr.next()` has been called to exhaust results) is being iterated a second time.
fixIf multiple iterations are needed, ensure `GlideRecord` is created with `rewindable=True` (which is the default behavior). If using `gr.next()`, call `gr.rewind()` before starting a new iteration. Pythonic `for` loops handle this more gracefully.
Unexpectedly, all records in the table were updated instead of just the queried ones using update_multiple().
Directly setting a field property (`gr.field = 'value'`) before calling `update_multiple()` instead of using the `set_value()` method.
fixAlways use `gr.set_value('field_name', 'new_value')` when preparing a `GlideRecord` object for `update_multiple()` to ensure the update applies only to records matching the query. Upgrade
Version history
1.2.1latest on PyPI · released Feb 11, 2026
Audit
Dependencies
No dependency data recorded yet.