dwt: In my tests at least this works fine on python2, as unicode and str are much more compatible there. I don't quite now wether there could be a reason old instances could have used a different encoding than ascii here, but if that was everything there was, then this is an actual fix for the problem.

I'm writing a test case right now, so lets see what the build server has to say about that.
dwt: @icemac I hope that I have addressed your comments - and would be glad to get this to mergeable.
dwt: @Icemac: I have to say I'm a bit lost why the test fails on Travis - it does work locally, and also seems to be of the same structure as the example you gave. Can you perhaps give a hint what Travis is annoyed about here?
dwt: Ah, I get it, this depends on https://github.com/zopefoundation/Zope/commit/4a6338876f15fb01f49c5b07f54e0bda39bab009 which hasn't been released yet.

I'll fix this for now, but feel free to drop that commit if you get around to releasing the other fix.
icemac: I'd appreciate to wait with the merge of this PR until the next Zope release (hopefully by the end of this week) so the `login` method can be used.
icemac: Zope 4.0b8 is released, so the `login` method can be used now.
diff --git a/CHANGES.rst b/CHANGES.rst
index 45d207d..7bc1f90 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -6,6 +6,9 @@ Changelog
 
 - Flake8 the code.
 
+- Ignored exception types no longer accidentally get converted to bytes and back
+  on Python 3.
+  (`#13 <https://github.com/zopefoundation/Products.SiteErrorLog/issues/13>`_)
 
 5.0 (2018-11-06)
 ----------------
diff --git a/src/Products/SiteErrorLog/SiteErrorLog.py b/src/Products/SiteErrorLog/SiteErrorLog.py
index a1250e3..c4b60a5 100644
--- a/src/Products/SiteErrorLog/SiteErrorLog.py
+++ b/src/Products/SiteErrorLog/SiteErrorLog.py
@@ -255,7 +255,8 @@ class SiteErrorLog(SimpleItem):
         return {
             'keep_entries': self.keep_entries,
             'copy_to_zlog': self.copy_to_zlog,
-            'ignored_exceptions': self._ignored_exceptions}
+            'ignored_exceptions': self._ignored_exceptions
+        }
 
     security.declareProtected(log_to_event_log, 'checkEventLogPermission')
 
@@ -277,6 +278,8 @@ class SiteErrorLog(SimpleItem):
             self.checkEventLogPermission()
         self.keep_entries = int(keep_entries)
         self.copy_to_zlog = copy_to_zlog
+        # filter out empty lines
+        # ensure we don't save exception objects but exceptions instead
         self._ignored_exceptions = tuple(
             [_f for _f in map(str, ignored_exceptions) if _f])
         if RESPONSE is not None:
diff --git a/src/Products/SiteErrorLog/www/main.pt b/src/Products/SiteErrorLog/www/main.pt
index fbe4aa7..cd992a5 100644
--- a/src/Products/SiteErrorLog/www/main.pt
+++ b/src/Products/SiteErrorLog/www/main.pt
@@ -13,17 +13,23 @@
 		tal:define="props container/getProperties">
 
 		<div class="form-group row">
-			<label for="id" class="form-label col-sm-5 col-md-4">Number of exceptions to keep</label>
+			<label for="keep_entries" class="form-label col-sm-5 col-md-4">Number of exceptions to keep</label>
 			<div class=" col-sm-7 col-md-8">
-				<input type="text" class="form-control" name="keep_entries" 
+				<input
+					type="text"
+					id="keep_entries"
+					class="form-control"
+					name="keep_entries" 
 					tal:attributes="value props/keep_entries" />
 			</div>
 		</div>
 
 		<div class="form-group row">
-			<label for="id" class="form-label col-sm-5 col-md-4">Copy exceptions to the event log</label>
+			<label for="copy_to_zlog" class="form-label col-sm-5 col-md-4">Copy exceptions to the event log</label>
 			<div class=" col-sm-7 col-md-8">
-				<input type="checkbox"
+				<input 
+					type="checkbox"
+					id="copy_to_zlog"
 					class="checkbox-list-item" 
 					name="copy_to_zlog"
 					tal:attributes="checked props/copy_to_zlog;
@@ -32,10 +38,15 @@
 		</div>
 
 		<div class="form-group row">
-			<label for="id" class="form-label col-sm-5 col-md-4">Ignored exception types</label>
+			<label for="ignored_exceptions" class="form-label col-sm-5 col-md-4">Ignored exception types</label>
 			<div class=" col-sm-7 col-md-8">
-				<textarea name="ignored_exceptions:lines" class="form-control" rows="3"
-					tal:content="python: '\n'.join(props['ignored_exceptions'])"></textarea>
+				<textarea
+					id="ignored_exceptions"
+					class="form-control"
+					name="ignored_exceptions:ulines"
+					rows="3"
+					tal:content="python: '\n'.join(props['ignored_exceptions'])"
+				></textarea>
 			</div>
 		</div>
 

Py3: ignored exception types gets converted to bytes and back accidentally
Thus adding a b'...' surrounding each time the page is saved.
diff --git a/src/Products/SiteErrorLog/tests/testSiteErrorLog.py b/src/Products/SiteErrorLog/tests/testSiteErrorLog.py
index 1571460..56d5520 100644
--- a/src/Products/SiteErrorLog/tests/testSiteErrorLog.py
+++ b/src/Products/SiteErrorLog/tests/testSiteErrorLog.py
@@ -18,10 +18,15 @@ import unittest
 
 import transaction
 from Testing.makerequest import makerequest
+import Testing.testbrowser
+import Testing.ZopeTestCase
 from zope.component import adapter, provideHandler
 from zope.event import notify
 from ZPublisher.pubevents import PubFailure
 import Zope2
+import Zope2.App
+
+from ..SiteErrorLog import manage_addErrorLog
 
 from Products.SiteErrorLog.interfaces import IErrorRaisedEvent
 
@@ -177,3 +182,39 @@ class SiteErrorLogTests(unittest.TestCase):
         # Need to make sure that the __error_log__ hook gets cleaned up
         self.app._delObject('error_log')
         self.assertEqual(getattr(self.app, '__error_log__', None), None)
+
+
+class SiteErrorLogUITests(Testing.ZopeTestCase.FunctionalTestCase):
+
+    def setUp(self):
+        super(SiteErrorLogUITests, self).setUp()
+
+        Zope2.App.zcml.load_site(force=True)
+
+        uf = self.app.acl_users
+        uf.userFolderAddUser('manager', 'manager_pass', ['Manager'], [])
+
+        # Why is this neccessary, shouldn't the test get a new app every time?
+        if not hasattr(self.app, 'error_log'):
+            manage_addErrorLog(self.app)
+        self.error_log = self.app.error_log
+
+        self.browser = Testing.testbrowser.Browser()
+        self.browser.login('manager', 'manager_pass')
+        self.browser.open('http://localhost/error_log/manage_main')
+
+    def testSubmitRetainsIgnoredExceptionsUnchanged(self):
+        # Checks the fix for
+        # https://github.com/zopefoundation/Products.SiteErrorLog/issues/13
+        ignoredExceptions = self.browser.getControl(
+            label='Ignored exception types')
+        self.assertEqual(
+            ignoredExceptions.value,
+            'Unauthorized\nNotFound\nRedirect')  # default value
+        ignoredExceptions.value = 'Unauthorized\nFnord'
+        self.assertNotIn('Changed properties', self.browser.contents)
+        self.browser.getControl('Save Changes').click()
+        self.assertIn('Changed properties', self.browser.contents)
+        ignoredExceptions = self.browser.getControl(
+            label='Ignored exception types')
+        self.assertEqual(ignoredExceptions.value, 'Unauthorized\nFnord')

pip install -e .
parse_log_pytest
pytest
pytest coverage flake8
pip install -U setuptools zc.buildout
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
AccessControl==5.7
Acquisition==4.13
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
AuthEncoding==4.3
beautifulsoup4==4.12.3
BTrees==4.11.3
certifi==2021.5.30
cffi==1.15.1
Chameleon==3.10.2
coverage==6.2
DateTime==4.9
DocumentTemplate==4.3
ExtensionClass==4.9
flake8==5.0.4
importlib-metadata==4.2.0
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
mccabe==0.7.0
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
MultiMapping==4.1
multipart==1.1.0
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
PasteDeploy==2.1.1
Persistence==3.6
persistent==4.9.3
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
-e git+https://github.com/zopefoundation/Products.SiteErrorLog.git@300a3bf9726035bc0a40bfbf434a6e0c5c21bed6#egg=Products.SiteErrorLog
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pycodestyle==2.9.1
pycparser==2.21
pyflakes==2.5.0
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
python-gettext==4.1
pytz==2025.2
RestrictedPython==6.2
roman==3.3
six==1.17.0
soupsieve==2.3.2.post1
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
transaction==3.1.0
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
waitress==2.0.0
WebOb==1.8.9
WebTest==3.0.0
WSGIProxy2==0.5.1
z3c.pt==3.3.1
zc.buildout==3.3
zc.lockfile==2.0
ZConfig==3.6.1
zExceptions==4.3
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work
ZODB==5.8.1
zodbpickle==2.6
Zope==5.7.3
zope.annotation==4.8
zope.browser==2.4
zope.browsermenu==4.4
zope.browserpage==4.4.0
zope.browserresource==4.4
zope.cachedescriptors==4.4
zope.component==5.1.0
zope.configuration==4.4.1
zope.container==4.10
zope.contentprovider==4.2.1
zope.contenttype==4.6
zope.datetime==4.3.0
zope.deferredimport==4.4
zope.deprecation==4.4.0
zope.dottedname==5.0
zope.event==4.6
zope.exceptions==4.6
zope.filerepresentation==5.0.0
zope.globalrequest==1.6
zope.hookable==5.4
zope.i18n==4.9.0
zope.i18nmessageid==5.1.1
zope.interface==5.5.2
zope.lifecycleevent==4.4
zope.location==4.3
zope.pagetemplate==4.6.0
zope.processlifetime==2.4
zope.proxy==4.6.1
zope.ptresource==4.3.0
zope.publisher==6.1.0
zope.schema==6.2.1
zope.security==5.8
zope.sequencesort==4.2
zope.site==4.6.1
zope.size==4.4
zope.structuredtext==4.4
zope.tal==4.5
zope.tales==5.2
zope.testbrowser==5.6.1
zope.testing==5.0.1
zope.traversing==4.4.1
zope.viewlet==4.3

name: Products.SiteErrorLog
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - accesscontrol==5.7
      - acquisition==4.13
      - authencoding==4.3
      - beautifulsoup4==4.12.3
      - btrees==4.11.3
      - cffi==1.15.1
      - chameleon==3.10.2
      - coverage==6.2
      - datetime==4.9
      - documenttemplate==4.3
      - extensionclass==4.9
      - flake8==5.0.4
      - importlib-metadata==4.2.0
      - mccabe==0.7.0
      - multimapping==4.1
      - multipart==1.1.0
      - pastedeploy==2.1.1
      - persistence==3.6
      - persistent==4.9.3
      - pycodestyle==2.9.1
      - pycparser==2.21
      - pyflakes==2.5.0
      - python-gettext==4.1
      - pytz==2025.2
      - restrictedpython==6.2
      - roman==3.3
      - setuptools==59.6.0
      - six==1.17.0
      - soupsieve==2.3.2.post1
      - transaction==3.1.0
      - waitress==2.0.0
      - webob==1.8.9
      - webtest==3.0.0
      - wsgiproxy2==0.5.1
      - z3c-pt==3.3.1
      - zc-buildout==3.3
      - zc-lockfile==2.0
      - zconfig==3.6.1
      - zexceptions==4.3
      - zodb==5.8.1
      - zodbpickle==2.6
      - zope==5.7.3
      - zope-annotation==4.8
      - zope-browser==2.4
      - zope-browsermenu==4.4
      - zope-browserpage==4.4.0
      - zope-browserresource==4.4
      - zope-cachedescriptors==4.4
      - zope-component==5.1.0
      - zope-configuration==4.4.1
      - zope-container==4.10
      - zope-contentprovider==4.2.1
      - zope-contenttype==4.6
      - zope-datetime==4.3.0
      - zope-deferredimport==4.4
      - zope-deprecation==4.4.0
      - zope-dottedname==5.0
      - zope-event==4.6
      - zope-exceptions==4.6
      - zope-filerepresentation==5.0.0
      - zope-globalrequest==1.6
      - zope-hookable==5.4
      - zope-i18n==4.9.0
      - zope-i18nmessageid==5.1.1
      - zope-interface==5.5.2
      - zope-lifecycleevent==4.4
      - zope-location==4.3
      - zope-pagetemplate==4.6.0
      - zope-processlifetime==2.4
      - zope-proxy==4.6.1
      - zope-ptresource==4.3.0
      - zope-publisher==6.1.0
      - zope-schema==6.2.1
      - zope-security==5.8
      - zope-sequencesort==4.2
      - zope-site==4.6.1
      - zope-size==4.4
      - zope-structuredtext==4.4
      - zope-tal==4.5
      - zope-tales==5.2
      - zope-testbrowser==5.6.1
      - zope-testing==5.0.1
      - zope-traversing==4.4.1
      - zope-viewlet==4.3
prefix: /opt/conda/envs/Products.SiteErrorLog

src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogUITests::testSubmitRetainsIgnoredExceptionsUnchanged
src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testCleanup src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testEntryID src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testEventSubscription src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testForgetException src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testIgnoredException src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testInstantiation src/Products/SiteErrorLog/tests/testSiteErrorLog.py::SiteErrorLogTests::testSimpleException
src/Products/SiteErrorLog/SiteErrorLog.py src/Products/SiteErrorLog/www/main.pt CHANGES.rst
src/Products/SiteErrorLog/SiteErrorLog.py src/Products/SiteErrorLog/www/main.pt CHANGES.rst