2016-06-07 4 views
0

Мы создаем программное обеспечение, которое считывает тысячи XML-файлов и импортирует их содержимое в базу данных SQLite с использованием SQLAlchemy.Ошибка многопроцессорности и SQLAlchemy

Здесь Вы можете найти соответствующие части нашего кода:

Файл 1:

from multiprocessing.dummy import Pool as ThreadPool 
... 
for file in os.listdir(path): 
    if file.endswith("-endpoint.xml"): 
     xmls.append([self.database, os.path.join(path, file), self.debug]) 

pool = ThreadPool(threads) 
try: 
    def multi_run_wrapper(args): 
     return collectors.import_asset(*args) 

    results = pool.map(multi_run_wrapper, xmls) 
    pool.close() 
    pool.join() 
except: 
    if self.debug: 
     traceback.print_exc(file=sys.stdout) 

Файл 2, часть 1:

def import_asset(db, xml, debug = False): 
    tree = ET.parse(xml) 
    root = tree.getroot() 
    signcheck = root.find('Signcheck') 
    usersArray = [] 
    running_processes = [] 
    autoruns = [] 

    machine_id = add_machine(root, xml, db, debug) 

Файл 2, часть 2:

def add_machine(root, file_path, db, debug = False): 
    ... 
    machine = Machine(hostname=hostname, operating_system=operating_system, version=Version) 
    db.add(machine) 
    db.commit() 

Файл 3:

На протяжении всего кода, 'БД' является то, что возвращаемое значение этой функции:

def open(sqlite_db_path = None): 
    engine = create_engine('sqlite:///' + sqlite_db_path) 
    session = sessionmaker() 
    session.configure(bind=engine) 
    return scoped_session(session()) 

Сообщение об ошибке:

TypeError: 'Session' object is not callable 

Мы прочитали here, что scoped_session() не возвращается истинный объект Session(). Но мы не смогли использовать эту информацию, чтобы исправить наш код.

Заранее благодарю вас за помощь в этом препятствии.

+0

Зачем вы называете 'scoped_session (session())'? вместо того, чтобы передавать объект как 'scoped_session (session)'? Очевидно, что ошибка говорит, что объект сеанса, созданный с помощью sessionmaker(), не может быть вызван. –

+0

'scoped_session (sessionmaker (bind = engine))', передать фабрику сеансов, созданную sessionmaker, вместо «Session», созданной фабрикой (вызов). –

ответ

3

Вы вызываете фабрику сеанса session, когда вам нужно позвонить вместо scoped_session (см. Contextual/Thread-local Sessions).

Так оно и должно быть

scoped_session(session)() 

вместо

scoped_session(session()) 

Для того, чтобы избежать путаницы, я бы рекомендовал переименовать session в session_factory. Так что-то подобное должно работать:

def open(sqlite_db_path = None): 
    engine = create_engine('sqlite:///' + sqlite_db_path) 
    session_factory = sessionmaker(bind=engine) 
    return scoped_session(session_factory)() 
2

Чтобы исправить это было просто заменить это:

def open(sqlite_db_path = None): 
    engine = create_engine('sqlite:///' + sqlite_db_path) 
    session = sessionmaker() 
    session.configure(bind=engine) 
    return scoped_session(session()) 

С этим:

engine = create_engine('sqlite:///' + sqlite_db_path) 
session_factory = sessionmaker(bind=engine) 
return scoped_session(session_factory) 

Спасибо всем людям, которые откликнулись на этот нить.

Смежные вопросы