800万XML以上のテキストファイルの前処理履歴を記入
一.背景
いくつかのニーズのため、最近数ヶ月で生成されたxmlファイルを前処理し、ラベル内のデータを抽出して分析する必要があります.これらの前処理が必要なデータは約280 GB前後880万余りで、gyslディレクトリの下に保存されています.gyslの次の層は日によって命名され、いくつかのディレクトリに分かれています.次の層のディレクトリの下には複数のディレクトリがあります.私たちが必要なxmlディレクトリはこの層にあります.このディレクトリの下にあるxmlファイルをPythonスクリプトで処理し、処理結果を日単位(ソースファイルと一致)で~/tempディレクトリに保存する必要があります.
二.オペレーションプロセス
2.1 Pythonスクリプトの準備.
2.2 Shellスクリプトの準備.
見ていると少し骨が折れるので、直してください.
2.3スクリプトを実行します.
この手順は、いくつかのビジネス機密に関連するものではありません.Pythonスクリプトがあるディレクトリの下で、Shellスクリプトを実行すればいいです.
三.問題にぶつかる
3.1 “Argument list too long”.
あるディレクトリのファイルの移動、コピー、削除操作を実行すると、コマンドの実行に失敗した「Argument list too long」というメッセージが表示されます.このディレクトリのファイル数は30万を超え、操作コマンドは以下の通りです.
ヒント:
ソリューション:
rm,mvも同様で,忙しくて他の解決策を検討し続けなかった.
3.2デュアルforサイクルの実行効率が低すぎます.
このコマンドを使ってこれらのファイルをコピーすれば、この日は過ぎ去るかもしれません.これは間違いなく不適切で,改善しなければならない.findも簡潔ではなく、その後最適化された.
3.3 Pythonシングルスレッドの実行効率が低すぎます.
Pythonスクリプトはマルチスレッドを使用して処理されます.でもたくさん解釈して、皆さん許してください^^;
四.まとめ
4.1全体的に今日これらのデータを処理するのはとても力があって、5000秒も差がなくて完成しました.私はコマンドを書いて動的に観察した.
4.2正規表現はいつでも使えます.特殊なタスクとPythonマルチスレッドを処理するか、grepコマンドをshellコマンドに直接書くととっくに終わっているかもしれません.
4.3マルチスレッド.bash shellのマルチスレッドはまだ使えないので、後で勉強しなければなりません.
4.4こんなにたくさん書いたのに、足りないところは皆さんに教えてもらいたい.
いくつかのニーズのため、最近数ヶ月で生成されたxmlファイルを前処理し、ラベル内のデータを抽出して分析する必要があります.これらの前処理が必要なデータは約280 GB前後880万余りで、gyslディレクトリの下に保存されています.gyslの次の層は日によって命名され、いくつかのディレクトリに分かれています.次の層のディレクトリの下には複数のディレクトリがあります.私たちが必要なxmlディレクトリはこの層にあります.このディレクトリの下にあるxmlファイルをPythonスクリプトで処理し、処理結果を日単位(ソースファイルと一致)で~/tempディレクトリに保存する必要があります.
二.オペレーションプロセス
2.1 Pythonスクリプトの準備.
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import glob,os,sys, re
from concurrent.futures import ProcessPoolExecutor
import argparse
import random
def find_xs(str, list):
i = 0
for i in range(0,len(str)):
if str[i] in list:
return i
return -1
def segement_aux(para, OUT, sep_list, max_length, merge_prob):
pos = 0
res_sentence = ""
sentence_size = 0
while True:
#segment one line.
pos = find_xs(para,sep_list)
if pos == -1:
break
cur_sentence = para[:pos+1].strip()
cur_sentence_filtering = cur_sentence
res_sentence = res_sentence + cur_sentence_filtering
sentence_size = sentence_size + 1
if sentence_size == 2:
OUT.write(res_sentence + '
')
else:
rand = random.random()
if rand > merge_prob:
OUT.write(res_sentence + '
')
res_sentence = ""
sentence_size = 0
else:
sentence_size = sentence_size + 1
para = para[pos+1:]
def loadXMLfile(inputfile):
sep_list= ['。', '?', '!']
targetfolder = "Target"
max_length = 100000
merge_prob = 0.6
basefilename =os.path.basename(inputfile)
outputfile = targetfolder + '/'+ os.path.splitext(basefilename)[0] + ".tsv"
textSessionPattern = re.compile(r'(.*?) \s*', re.I|re.MULTILINE)
OUT = open(outputfile, 'w',encoding="utf8")
for line in open(inputfile,encoding="utf8"):
line = line.strip().rstrip("\r
")
alltextsessions = re.findall(textSessionPattern, line)
for textsession in alltextsessions:
textsession = re.sub(r'\t', r' ', textsession)
textsession = re.sub(r'\]+\>', r'', textsession)
textsession = re.sub(r'\{[^\}|\{]+\}', r'', textsession)
textsession = re.sub(r'\s+',r'',textsession)
OUT.write(textsession+'
')
OUT.close()
return outputfile
def processXMLfilesWithThreads(input):
with ProcessPoolExecutor() as executor:
xmlfiles = glob.glob(input + "/*.xml")
for xmlfile, outputfile in zip( xmlfiles, executor.map( loadXMLfile, xmlfiles) ):
print("Processed" + outputfile)
if __name__ == '__main__':
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required=True, help="the directory of input files")
args = ap.parse_args()
processXMLfilesWithThreads(input = args.input)
2.2 Shellスクリプトの準備.
for folder in `find /home/ivandu/gysl -path "*/xml" -print`;do mkdir Target;python3 XMLPreProcess.py --input $folder;mv Target ~/temp/$(echo $folder|awk -F "/" '{print $5}');done
見ていると少し骨が折れるので、直してください.
#!/bin/bash
for folder in `find /home/ivandu/gysl -path "*/xml" -print`;
do
mkdir Target;
python3 XMLPreProcess.py --input $folder;
mv Target ~/temp/$(echo $folder|awk -F "/" '{print $5}');
done
2.3スクリプトを実行します.
この手順は、いくつかのビジネス機密に関連するものではありません.Pythonスクリプトがあるディレクトリの下で、Shellスクリプトを実行すればいいです.
三.問題にぶつかる
3.1 “Argument list too long”.
あるディレクトリのファイルの移動、コピー、削除操作を実行すると、コマンドの実行に失敗した「Argument list too long」というメッセージが表示されます.このディレクトリのファイル数は30万を超え、操作コマンドは以下の通りです.
cp * ~/gysl_test
ヒント:
-sh: /bin/cp: Argument list too long
ソリューション:
for file in `ls`;do cp $file ~/gysl_test/;done
rm,mvも同様で,忙しくて他の解決策を検討し続けなかった.
3.2デュアルforサイクルの実行効率が低すぎます.
for folder in `find /home/ivandu/gysl/ -mindepth 2 -maxdepth 2 -print|grep "xml"`;do cd $folder;for file in $(ls);do cp $file ~/gysl_test/;done;done
このコマンドを使ってこれらのファイルをコピーすれば、この日は過ぎ去るかもしれません.これは間違いなく不適切で,改善しなければならない.findも簡潔ではなく、その後最適化された.
3.3 Pythonシングルスレッドの実行効率が低すぎます.
Pythonスクリプトはマルチスレッドを使用して処理されます.でもたくさん解釈して、皆さん許してください^^;
四.まとめ
4.1全体的に今日これらのデータを処理するのはとても力があって、5000秒も差がなくて完成しました.私はコマンドを書いて動的に観察した.
4.2正規表現はいつでも使えます.特殊なタスクとPythonマルチスレッドを処理するか、grepコマンドをshellコマンドに直接書くととっくに終わっているかもしれません.
4.3マルチスレッド.bash shellのマルチスレッドはまだ使えないので、後で勉強しなければなりません.
4.4こんなにたくさん書いたのに、足りないところは皆さんに教えてもらいたい.