My app structure is like this: src/Products/my_products/...
For the Python 3 migration I switched from the unmaintained LocalFs (which made files on the file system available as objects) to using a resourceDirectory via zcml.
Access via browser works like a charm via eg. ++resource++assets/images/ClassIcons/SoftwareLicence.png, which maps the access to src/Products/assets/images/ClassIcons/SoftwareLicence.png.
The ++ (as in your ++resource++assets) introduces a so called namespace (in your case with namespace type name resource and namespace name assets). Namespace lookup is supported by [un]restrictedTraverse. This implies, that you can e.g. use obj.unrestrictedTraverse("++resource++assets/images/ClassIcons/SoftwareLicence.png") (where obj is a Zope web object, typically your context object).