The manager module handles requests across multiple corpora. It should be the default interface to searching corpora.

New in v3 – previously most were static methods on corpus.corpora.Corpus, but that seemed inappropriate since these work across corpora.


music21.corpus.manager.cacheMetadataBundleFromDisk(corpusObject: Corpus) None

Update a corpus’ metadata bundle from its stored JSON file on disk.


Instantiate a specific corpus based on name:

>>> corpus.manager.fromName('core')
>>> corpus.manager.fromName('local')
<music21.corpus.corpora.LocalCorpus: 'local'>
>>> corpus.manager.fromName(None)
<music21.corpus.corpora.LocalCorpus: 'local'>

Note that this corpus probably does not exist on disk, but it’s ready to have paths added to it and to be stored on disk.

>>> corpus.manager.fromName('testDummy')
<music21.corpus.corpora.LocalCorpus: 'testDummy'>
music21.corpus.manager.getMetadataBundleByCorpus(corpusObject: corpora.Corpus) bundles.MetadataBundle

Return the metadata bundle for a single Corpus object

>>> cc = corpus.corpora.CoreCorpus()
>>> mdb1 = corpus.manager.getMetadataBundleByCorpus(cc)
>>> mdb1
<music21.metadata.bundles.MetadataBundle 'core': {... entries}>

This is the same as calling metadataBundle on the corpus itself, but this is the routine that actually does the work. In other words, it’s the call on the object that is redundant, not this routine.

>>> mdb1 is cc.metadataBundle

Non-existent corpus…

>>> lc = corpus.corpora.LocalCorpus('junk')
>>> mdb1 = corpus.manager.getMetadataBundleByCorpus(lc)
>>> mdb1
<music21.metadata.bundles.MetadataBundle 'junk': {0 entries}>
music21.corpus.manager.getWork(workName: str | Path, movementNumber: int | None = None, *, fileExtensions: Iterable[str] = ()) Path | list[pathlib.Path]

this parse function is called from corpus.parse() and does nothing differently from it.

Searches all corpora for a file that matches the name and returns it parsed.


a generator that iterates over the corpora (either as objects or as names) for use in pan corpus searching.

This test will only show the first two, because it needs to run the same on every system:

>>> for i, corpusObject in enumerate(corpus.manager.iterateCorpora()):
...     print(corpusObject)
...     if i == 1:
...        break
<music21.corpus.corpora.LocalCorpus: 'local'>

We can also get names instead… Note that the name of the main local corpus is ‘local’ not None

>>> for i, corpusName in enumerate(corpus.manager.iterateCorpora(returnObjects=False)):
...     print(corpusName)
...     if i == 1:
...        break
  • New in v3.


List the names of all user-defined local corpora.

The entry for None refers to the default local corpus.


List all available search field names:

>>> for field in corpus.manager.listSearchFields():
...     field
music21.corpus.manager.parse(workName: str | pathlib.Path, *, movementNumber: int | None = None, number: int | None = None, fileExtensions: Iterable[str] = (), forceSource: bool = False, format: str | None = None) stream.Score | stream.Part | stream.Opus

Read each corpus’s metadata bundle and store it in memory. str | None = None, field: str | None = None, *, corpusNames=None, fileExtensions: Iterable[str] | str = (), **keywords)

Search all stored metadata bundles and return a list of file paths.

This function uses stored metadata and thus, on first usage, will incur a performance penalty during metadata loading.

<music21.metadata.bundles.MetadataBundle {1235 entries}>
>>>'china', fileExtensions=('.mid',))
<music21.metadata.bundles.MetadataBundle {0 entries}>
>>>'bach', field='composer')
<music21.metadata.bundles.MetadataBundle {363 entries}>

Note the importance of good metadata – there’s almost 400 pieces by Bach in the corpus, but many do not have correct metadata entries.

This can also be specified as:

<music21.metadata.bundles.MetadataBundle {363 entries}>

Or, to get all the chorales (without using corpus.chorales.Iterator):

>>>'bach', numberOfParts=4)
<music21.metadata.bundles.MetadataBundle {368 entries}>

This function is implemented in corpus.manager as a method there but also directly available in the corpus module for ease of use.

The corpusNames parameter can be used to specify which corpora to search, for example:

...     'bach',
...     corpusNames=('core',),
...     )
<music21.metadata.bundles.MetadataBundle {564 entries}>
...     'bach',
...     corpusNames=('core',),
...     fileExtensions=('xml',),
...     )
<music21.metadata.bundles.MetadataBundle {412 entries}>

If corpusNames is None, all corpora known to music21 will be searched.

See usersGuide (chapter 11) for more information on searching