2014-02-18 3 views
-2

Я пытаюсь разделить очень большой текстовый файл на две части и выгрузить две части в две разные таблицы mysql. Я делаю это в python, проверяю текст по строкам и классифицирую каждую строку по коду категории.python записывает вывод в другой файл fifo pipe?

Теперь, после того как я разделил текст, как мне передать их в два отдельных файла fifo, чтобы я мог передать эти fifo в клиентские инструменты mysql?

+1

Что такое файл трубы? Почему бы просто не получить доступ к mysql через python? – msvalkon

+0

, который будет слишком медленным, чтобы вставлять каждую строку, через конвейер я могу использовать mysql 'load data', который очень быстрый, чем 'insert' – Suanmeiguo

+2

Можете ли вы еще раз объяснить, что вы имеете в виду, когда говорите «файл трубы»? – Bach

ответ

0

Я думаю, что вы хотите создать трубы для двух отдельных и, по-видимому, одновременного импорта MySQL из одного и того же сценария Python?

Хотя это не невозможно, чтобы сделать это через перенаправление оболочки, это будет болезненно. Ваш скрипт Python должен каким-то образом передать файловые дескрипторы своих труб в оболочку, поэтому ваш сценарий оболочки может перенаправить эти файловые дескрипторы в команды MySQL.

Гораздо проще решить это на Python с помощью модуля subprocess.

Я не знаю инструмент и синтаксис, которые вы надеетесь использовать для выполнения массовой загрузки; все, что вы нам сказали, это то, что вы хотите дать ему «трубу». Итак, я просто предполагаю, что это команда mysqlimport, упомянутая в ответе hbristow, и что она обрабатывает stdin через обычное соглашение Unix, дающее ему - как имя файла; так как это только для демонстрации актуальной интересной части, это не имеет большого значения в любом случае.

Итак:

from subprocess import Popen, stdin 

args = ['mysqlimport', my_db_name, '-'] 
with Popen(args, stdin=PIPE) as import1, Popen(args, stdin=PIPE) as import2: 
    with open('giantfile.txt') as f: 
     for line in f: 
      data = parse(line) 
      if belongs_in_import2(data): 
       import2.stdin.write(make_sql(data)) 
      else: 
       import1.stdin.write(make_sql(data)) 

Мы создали два отдельных дочерних процессов, каждый со своим собственным отдельным stdin трубы, и мы можем записать их так же, как мы можем, чтобы любые другие файлы.

Вам может понадобиться import1.stdin.close() и import2.stdin.close() если инструмент mysqlimport ожидает от вас, чтобы закрыть/EOF файл ввода, прежде чем на самом деле ждет от него, чтобы выйти.

Если вы используете Python 2.4-2.7, вы должны установить и использовать задний порт subprocess32. Если вы не можете сделать это по какой-либо причине (или если вы используете Python 3.0-3.1 и не можете обновить по какой-либо причине), здесь вы не можете использовать оператор with; вместо этого вам нужно явно указатьна трубы и wait процессы.

+0

Это здорово, по крайней мере, это показывает мне отдельный процесс, и что делает функция make_sql? что возвращает эта функция? – Suanmeiguo

+0

@Suanmeiguo: Он делает все, что вы хотите. Предположительно, вы пытаетесь, для каждой строки входных данных, генерировать либо строку данных, либо оператор в качестве вывода, чтобы перейти к загрузчику большого объема MySQL. Эта функция - это то место, где вы помещаете код, который генерирует этот вывод, и возвращает его как строку (включая конечную новую строку). – abarnert

1

Я предполагаю, что Вы желаете сделать, это назвать команду MySql

LOAD DATA INFILE 

без фактического создания INFILE. Вы можете попробовать использовать клиент mysqlimport командной строки, а также при условии, что он будет рад принять трубу, сделать что-то вроде:

python categorize.py --code x big_text_file.txt | mysqlimport db_name /dev/stdin 

где сценарий Python разбивает текстовый файл с помощью ввода кода в командной строке и выводит результат в виде строки, которая передается в mysqlimport.

+0

Но он, по-видимому, хочет создать две отдельные трубы, а не одну, поэтому это не сработает. – abarnert

+0

Абрамерт получил мою мысль. Я хочу создать две отдельные трубы. – Suanmeiguo