Addendum (2016-10-25): 10.2.1 a été publié, mais la situation ne semble pas s'améliorer dans ce cas. Postscript (2017-03-31): confirmé en 10.12.4. Il semble que cela ait été corrigé. Tu l'as fait!
sqlite3_sierra_exp.py
#!/usr/bin/env python
"""\
An example that crashes on macOS Sierra.
"""
from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from logging import getLogger, StreamHandler, Formatter
from logging import DEBUG
from multiprocessing import Process, freeze_support
from threading import Thread
import os
import sqlite3
import sys
import time
_DB_PATH = os.path.join(os.path.dirname(__file__), 'state.db')
def _connect(db_path):
conn = sqlite3.connect(db_path)
return conn
def get_count(db_path, name):
conn = _connect(db_path)
c = conn.cursor()
c.execute('''\
SELECT count FROM test_table
WHERE name = ?
''', (name,))
(count,) = c.fetchone()
conn.commit()
conn.close()
return count
def incrementer_process(db_path, name):
conn = _connect(db_path)
c = conn.cursor()
c.execute('''\
SELECT count FROM test_table
WHERE name = ?
''', (name,))
(count,) = c.fetchone()
c.execute('''\
INSERT OR REPLACE INTO test_table
(name, count)
VALUES (?, ?)
''', (name, count + 1))
conn.commit()
conn.close()
def main():
logger = getLogger(__name__)
handler = StreamHandler()
logger.addHandler(handler)
logger.setLevel(DEBUG)
handler.setLevel(DEBUG)
handler.setFormatter(Formatter('%(asctime)s %(message)s'))
logger.info('python version: {}'.format(sys.version))
logger.info('module_version: {}'.format(sqlite3.version))
logger.info('sqlite3_version: {}'.format(sqlite3.sqlite_version))
name = 'name'
db_path = _DB_PATH
conn = _connect(db_path)
c = conn.cursor()
c.execute('''\
DROP TABLE IF EXISTS
test_table
''')
c.execute('''\
CREATE TABLE IF NOT EXISTS
test_table (name text, count integer)
''')
c.execute('''\
CREATE UNIQUE INDEX IF NOT EXISTS
files_index ON test_table (name)
''')
c.execute('''\
INSERT OR REPLACE INTO test_table
(name, count)
VALUES (?, ?)
''', (name, 0))
conn.commit()
conn.close()
logger.debug('Creating a child')
child = Process(target=incrementer_process,
args=(db_path, name))
#child = Thread(target=incrementer_process,
# args=process_args,
# kwargs=process_kwargs)
child.start()
child.join()
logger.info('value: {}'.format(get_count(db_path, name)))
if __name__ == '__main__':
freeze_support()
main()
Créez une base de données sqlite3 dans le processus principal et incrémentez la valeur de 1 via multiprocessing.Process
.
Ce n'est pas une situation où les conditions de course se produisent.
C'est un peu bâclé, mais cela ne pose aucun problème avec therading.Thread
.
$ pyenv shell 3.5.2-nativesqlite3
$ ./sqlite3_sierra_exp.py
2016-10-24 22:14:29,065 python version: 3.5.2 (default, Oct 24 2016, 22:06:56)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)]
2016-10-24 22:14:29,065 module_version: 2.6.0
2016-10-24 22:14:29,065 sqlite3_version: 3.14.0
2016-10-24 22:14:29,072 Creating a child
2016-10-24 22:14:29,081 value: 0
Même si j'utilise pyenv, j'ai soudainement obtenu des résultats incroyables. Est-ce 0? ??
Si vous utilisez le Python intégré de Sierra ici ...
$ ./sqlite3_sierra_exp.py
2016-10-24 22:15:05,994 python version: 2.7.10 (default, Jul 30 2016, 18:31:42)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
2016-10-24 22:15:05,994 module_version: 2.6.0
2016-10-24 22:15:05,994 sqlite3_version: 3.14.0
2016-10-24 22:15:06,001 Creating a child
2016-10-24 22:15:06,009 value: 0
Hey! ??
Comparez avec le résultat de l'exécution sur Debian Jessie pour comparaison
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.6 (jessie)
Release: 8.6
Codename: jessie
$ pyenv shell system
$ ./sqlite3_sierra_exp.py
2016-10-24 22:16:21,316 python version: 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2]
2016-10-24 22:16:21,316 module_version: 2.6.0
2016-10-24 22:16:21,316 sqlite3_version: 3.8.7.1
2016-10-24 22:16:21,352 Creating a child
2016-10-24 22:16:21,368 value: 1
Eh bien, c'est vrai. C'est 1 ...
Je vais également l'essayer sous Windows. C'est une capture d'écran car il est difficile de copier et coller ...
C'est 1 ... (soupire
Pour conclure, cela semble être le résultat du bug suivant (exactement le problème de libsqlite3 fourni avec macOS). Apple-supplied libsqlite3 on OS X is not fork safe; can cause crashes
En attente de la correction de la librairie attachée à l'OS, un. Ou si vous apportez sqlite3 3.15.0 de Homebrew et que vous l'utilisez, ce symptôme lui-même disparaît. Inversement, si vous ne modifiez pas cette partie, toute version de Python peut être prise dans les problèmes ci-dessus.
$ brew info sqlite3
sqlite: stable 3.15.0 (bottled) [keg-only]
Command-line interface for SQLite
https://sqlite.org/
/usr/local/Cellar/sqlite/3.9.2 (10 files, 2.8M)
Poured from bottle on 2016-08-03 at 14:21:08
/usr/local/Cellar/sqlite/3.15.0 (11 files, 2.9M)
Poured from bottle on 2016-10-24 at 18:12:13
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/sqlite.rb
==> Dependencies
Recommended: readline ✔
Optional: icu4c ✔
==> Options
--universal
Build a universal binary
--with-dbstat
Enable the 'dbstat' virtual table
--with-docs
Install HTML documentation
--with-fts
Enable the FTS3 module
--with-fts5
Enable the FTS5 module (experimental)
--with-functions
Enable more math and string functions for SQL queries
--with-icu4c
Enable the ICU module
--with-json1
Enable the JSON1 extension
--with-secure-delete
Defaults secure_delete to on
--with-session
Enable the session extension
--with-unlock-notify
Enable the unlock notification feature
--without-readline
Build without readline support
--without-rtree
Disable the R*Tree index module
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.
macOS provides an older sqlite3.
Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:
LDFLAGS: -L/usr/local/opt/sqlite/lib
CPPFLAGS: -I/usr/local/opt/sqlite/include
PKG_CONFIG_PATH: /usr/local/opt/sqlite/lib/pkgconfig
$ LDFLAGS="-L/usr/local/opt/sqlite/lib" \
CPPFLAGS="-I/usr/local/opt/sqlite/include" \
PKG_CONFIG_PATH="/usr/local/opt/sqlite/lib/pkgconfig" \
pyenv install 3.5.2
(Omission)
$ pyenv shell 3.5.2
$ ./sqlite3_sierra_exp.py
2016-10-24 22:19:30,973 python version: 3.5.2 (default, Oct 24 2016, 21:47:12)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.38)]
2016-10-24 22:19:30,973 module_version: 2.6.0
2016-10-24 22:19:30,973 sqlite3_version: 3.15.0
2016-10-24 22:19:30,978 Creating a child
2016-10-24 22:19:30,992 value: 1
Le fait est que la partie sqlite3_version a changé.
Sous l'environnement Python de pyenv, le pop-up indiquant qu'il s'est écrasé n'apparaît pas. Puisque Process plante à un niveau que même ʻexception de BaseException` ne peut pas attraper, le crash lui-même n'est pas remarqué.
j'étais fatigué
Recommended Posts