92711


**実行環境**  
OS: Windows 10  
言語: Python 3.x  
ライブラリ: 標準ライブラリのみ (pandas, numpy等は使えない）

### 作成しているプログラムについて

AWS CloudWatch Logsのログをcsvで取得したものを成形するプログラムを作成しています。  
CloudWatchでcsvデータを取得しますと、下記のcsvデータを取得します。

#### CloudWatch logsのcsvデータ一部 例

[code]

    timestamp,message
    0000000000000,"START RequestId: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Version: $LATEST
    "
    1111111111111,"[INFO]   2022-12-09T00:45:15.119Z    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA    testlog1。
    "
    2222222222222,"[INFO]   2022-12-09T00:45:15.120Z    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA    testlog2。
    "
    
[/code]

こちらのログを見てみますと、ログレベル 日付時刻、RequestId、ログが一緒になっております。  
この状態ですと、Excelに張り付けた場合、これらがくっついて反映してしまいます。  
ですのでこれらのデータがくっつかないよう、次のようなcsvデータに成形しようと考えております。

#### 成形後のcsvデータ

[code]

    timestamp,message
    0000000000000, START RequestId: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Version: $LATEST,
    1111111111111, [INFO], 2022-12-09T00:45:15.119Z, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, testlog1。,
    2222222222222, [INFO], 2022-12-09T00:45:15.120Z, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, testlog2。
    
[/code]

### やりたいこと

上記のようにcsvデータを成形したいのですが、縦に並んでしまいうまくいきません。  
やり方をご教示いただけると幸いです。

### 試したこと

下記のコードのように、次のことを行いました。

  1. 実際のログを読み込み、csvalldataの配列を作成する。
  2. ログレベル、日付等がくっついているのは配列の一番目に該当しますのでsplitで\tで分割する。  
(csvファイルをリスト化すると、ログレベルや日付のスペースは `\t` で表示されていた。)

  3. 分割したリストsplitlistに0番目に該当するcol_0を追加する。
  4. csvalldataにsplitlistを追加する。データをループする。
  5. リストのままcsv化すると[]が入ってしまうのでリストから要素を取り出し並べなおす。

私なりに考え、書いたのですが、csvデータの取得はできませんでした。  
原因を教えていただけると幸いです。

また、より効率の良いやり方等があればそちらについても教えていただけるとありがたいです。

[code]

    import csv
    import datetime
    
    #open()ファイルの読み込み
    file = open("log_before.csv", "r", encoding="utf-8") 
    
    #csvファイルの読み込み
    reader = csv.reader(file)
    
    csvalldata = []
    for num in reader:
        col_0 = num[0] 
        col_1 = num[1]
        splitlist = col_1.split('\t')
        splitlist.insert(0, col_0) #0番目要素追加
        csvalldata.append(splitlist)
    
    print("A.リスト状態確認", csvalldata)          
    newdata = ''   
    for i in csvalldata:
      for j in i:
        newdata = newdata + '"' + j +'", '
        print("newdata", newdata)
    
    #open()ファイルの読み込み エンコーディング指定
    now = datetime.datetime.now() #現在時刻取得
    out_filename = 'log_after_{0:%M%S}.csv'.format(now) 
    newfile = open(out_filename, "w",encoding="utf-8") 
    
    #csvファイルの書き込み
    writer = csv.writer(newfile)
    writer.writerows(newdata)
    print("csvファイルを作成：", out_filename)
    
[/code]


CC BY-SA 4.0
2022-12-11T15:07:14.703
92707
2022-12-12T02:29:50.750
2022-12-12T00:43:58.617
3060
47546
question
python aws csv excel
AWS CloudWatch Logs のログの成形ができない


> ライブラリ:標準ライブラリのみ(pandas, numpy等は使えない）

> また、より効率の良いやり方等があればそちらについても教えていただけるとありがたいです。

ライブラリに制約がある環境下ですと、VBAと大差のない泥くさいコードにならざるを得ないと思われます。最終的にExcelに読み込むのでしたら、最初からExcelで処理することをお勧めします。ExcelにはCSVファイルの整形のようなデータ処理のために
[**Power Query**](https://support.microsoft.com/ja-jp/office/excel-%E3%81%AE-
power-
query-%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6-7104fbee-9e62-4cb9-a02e-5bfb1a6c536a)
という機能が搭載されています。  
「データ」-「新しいクエリ」-「空のクエリ」を選ぶとPower Queryエディターが立ち上がります。ここで「詳細エディター」を選ぶとコード入力できます。

[code]

    let
        csv = Csv.Document(File.Contents("C:\Path\To\log_before.csv"),[Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
        headered = Table.PromoteHeaders(csv, [PromoteAllScalars=true]),
        splitted = Table.SplitColumn(headered, "message", Splitter.SplitTextByDelimiter("#(tab)", QuoteStyle.None), {"col_0", "col_1", "col_2", "col_3"}),
        transformed = Table.TransformColumnTypes(splitted,{{"timestamp", Int64.Type}, {"col_0", type text}, {"col_1", type datetime}, {"col_2", type text}, {"col_3", type text}})
    in
        transformed
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/nlWAv.png)](https://i.stack.imgur.com/nlWAv.png)

[![画像の説明をここに入力](https://i.stack.imgur.com/3XxaO.png)](https://i.stack.imgur.com/3XxaO.png)

どのように読み込んだのかはExcelが保持していますので、メニューの「更新」から再実行することも可能です。最低限の記述しかしていませんが、カラムのデータ型変換なども行えますし、ファイル名が動的に変化する場合でも
[`Folder.Files`](https://learn.microsoft.com/ja-jp/powerquery-m/folder-files)
を使うことでファイルを探索することも可能です。


CC BY-SA 4.0
2022-12-11T21:26:58.073
92710
2022-12-11T21:26:58.073
4236
92707
answer


AWSCLI と jq コマンドが利用可能であれば 1~3 行で済むのですが、Python + CSV モジュールの場合は(一例として)以下の様になります。  
※ 念の為、`csv.QUOTE_NONNUMERIC` を指定しています

[code]

    import csv
    import datetime
    import re
    
    now = datetime.datetime.now()
    out_filename = 'log_after_{0:%M%S}.csv'.format(now) 
    
    with open('log_before.csv', 'r', encoding='utf-8') as file, \
         open(out_filename, 'w',encoding='utf-8') as newfile:
        reader = csv.reader(file)
        writer = csv.writer(newfile, quoting=csv.QUOTE_NONNUMERIC)
        for col_0, col_1 in reader:
            splitlist = [col_1.strip()] if re.search(r'^START', col_1) else \
                        [c.strip() for c in re.split(r'\s+', col_1, maxsplit=3)]
            splitlist.insert(0, col_0)
            writer.writerow(splitlist)
    
    print('csvファイルを作成：', out_filename)
    
[/code]


CC BY-SA 4.0
2022-12-12T02:16:48.093
92711
2022-12-12T02:29:50.750
2022-12-12T02:29:50.750
47127
47127
92707
answer