93253


dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し、pythonからmysqlに接続しfetchallでテーブルを表示しようとすると日本語が文字化けしました。

MySQLイメージ: mysql:5.7  
Pythonイメージ: 3.7  
mysql-connector-python: 8.0.31  
サーバーとクライアントのIP: 異なる

[docker-compose_yml]

[code]

    version: '3'
    
    services:
      # MySQL
      db:
        build:
          context: .
          dockerfile: ./db/Dockerfile
        container_name: mysql_host
        environment:
          MYSQL_ROOT_PASSWORD: pass
          MYSQL_DATABASE: test_database
          MYSQL_USER: user
          MYSQL_PASSWORD: pass
          TZ: 'Asia/Tokyo'
        volumes:
        - ./db/data:/var/lib/mysql
        - ./log/mysql:/var/log/mysql
        - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
        ports:
        - 3306:3306
        ## For static IP address
        networks:
          python_network:
            ipv4_address: 192.168.2.2              
    
    ## python3 
      python3:
        restart: always
        build:
          context: .
          dockerfile: ./python/Dockerfile
        container_name: "python3"
        working_dir: "/root/src"
        tty: true
        volumes:
          - ./python:/root/src
        links:
          - db 
        networks:
          - python_network
    
    networks: 
      python_network:
        driver: bridge
        ipam:
          driver: default
          config:
           - subnet: 192.168.2.0/24
             gateway: 192.168.2.1
    
    
[/code]

[/db/Dockerfile]

[code]

    FROM mysql:5.7
    ADD  ./db/my.cnf /etc/mysql/conf.d/my.cnf
    RUN chmod 644 /etc/mysql/conf.d/my.cnf
    
[/code]

[/python/Dockerfile]

[code]

    FROM python:3.7
    
    RUN pip install --upgrade pip
    RUN pip install --upgrade setuptools
    RUN pip install mysql-connector-python
    
[/code]

[my.cnf](latin1;utf8mb4,utf8でそれぞれ試した。

[code]

    [mysqld]
    # 文字コード、整合順序の設定
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    secure-file-priv=""
    
    [mysql]
    default-character-set=utf8mb4
    
    [client]
    default-character-set=utf8mb4
    user = user
    password = pass
    
[/code]

mysqlコンテナに入り直接表示してみた所、文字コードの設定により文字化けしたりしなかったりします。

[code]

    select * from sample;
    
[/code]

**文字化けする場合:**

[code]

    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8mb4                    |
    | character_set_connection | utf8mb4                    |
    | character_set_database   | utf8mb4                    |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8mb4                    |
    | character_set_server     | utf8mb4                    |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    
[/code]

**文字化けしない場合:**

[code]

    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | latin1                     |
    | character_set_connection | utf8mb4                    |
    | character_set_database   | utf8mb4                    |
    | character_set_filesystem | binary                     |
    | character_set_results    | latin1                     |
    | character_set_server     | utf8mb4                    |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    
[/code]

扱うデータの都合上、latin1で取得すると正しく表示されるようです。  
また、メモ帳(utf8)でレコードを開くと文字化けしていました。

そこでpythonのコードから文字コードを変更し、設定を表示しつつ再度試した所、

[code]

    ('character_set_client', 'latin1')
    ('character_set_connection', 'utf8mb4')
    ('character_set_database', 'utf8mb4')
    ('character_set_filesystem', 'binary')
    ('character_set_results', 'latin1')
    ('character_set_server', 'utf8mb4')
    ('character_set_system', 'utf8')
    ('character_sets_dir', '/usr/share/mysql/charsets/')
    
[/code]

と文字コードの設定は同じなのにpythonから読むと文字化けしてしまいした。charsetや文字コードの変更（全てutf8mb4またはutf8にする等）、色々試しましたが文字化けします。

[code]

    # coding: latin1
    import mysql.connector
    
    #pythonからmysqlに接続
    cnx = mysql.connector.connect(
    host='',
    port='3306',
    user='user',
    password='pass',
    database='test_database',
    charset='latin1'
        )
    cursor_=cnx.cursor()
    
    cursor_.execute("use test_database;")
    
    #文字コードを変更し設定の状況を取得
    query1 = "SET CHARACTER SET latin1;"
    cursor_.execute(query1)
    
    cursor_.execute("show variables like 'chara%';")
    rows = cursor_.fetchall()
    for row in rows:
      print (row)
    
    cursor_.execute("select * from test;")
    rows = cursor_.fetchall()
    for row in rows:
      print (row)
    
[/code]

また、printにcordingを付ける試みはtuple型であった為に失敗しました。これの解決法も不明です。

[code]

    for row in rows:
      print (row.cording(utf8やlatin1))
    
[/code]

[code]

    'tuple' object has no attribute 'encord'
    
[/code]

どなたかlatin1で取得したデータをpythonから表示する方法をご存知ないでしょうか


CC BY-SA 4.0
2023-01-07T17:11:09.463
93233
2023-01-09T06:19:50.987
2023-01-09T06:19:50.987
55611
55611
question
python mysql docker
pythonからmysqlに接続すると日本語が文字化けする


# 回答ではありません

質問が全く正確でないため、また原因が不明なため、回答にはなっていません。

## 前提

質問が以下のコードで構築される環境だと仮定します。

MySQLイメージ: mysql:8.0.31  
Python: 3.10.9  
mysql-connector-python: 8.0.31  
PyMySQL: 1.0.2  
サーバーとクライアントのIP: 異なる

### コード

※空のディレクトリで実行すること  
**create_env.sh**

[code]

    WAIT_SETUP_MYSQL=10
    cat >my.cnf <<EOF
    [mysqld]
    character-set-server = utf8mb4
    collation-server = utf8mb4_unicode_ci
    #[client]
    #default-character-set=utf8mb4
    EOF
    cat >docker-compose.yml <<EOF
    version: '3.1'
    services:
      db:
        image: mysql:8
        command: --default-authentication-plugin=mysql_native_password 
        volumes:
          - ./data:/var/lib/mysql
          - ./logs:/var/log/mysql
          - ./my.cnf:/etc/mysql/conf.d/my.cnf
        ports:
          - 3306:3306
        environment:
          MYSQL_ROOT_PASSWORD: example
          TZ: 'Asia/Tokyo'
      python:
        image: python:3.10
        volumes:
          - ./python/:/opt/project/
    EOF
    docker-compose up -d db
    docker-compose exec -T db bash <<EOF
    while sleep 1;do if [ -S /var/run/mysqld/mysqld.sock ];then break;fi;done
    sleep $WAIT_SETUP_MYSQL
    EOF
    docker-compose exec -T db bash <<EOF
    mysql --user=root --password=example
    use mysql
    create user \`user\`@\`%\` IDENTIFIED BY 'python';
    create database sampledb character set utf8mb4 collate utf8mb4_bin;
    grant all on sampledb.* to user;
    use sampledb
    create table sample(
    id varchar(20) primary key,
    name varchar(1024)
    );
    insert into sample values('1001', 'dockerを用いてpythonからmysqlに接続すると日本語が文字化けする');
    insert into sample values('1002', 'dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し');
    insert into sample values('1003', 'pythonからmysqlに接続しfetchallでテーブルを表示しようとすると');
    insert into sample values('1004', '             ');
    exit
    EOF
    docker-compose exec -T db bash <<EOF
    mysql --user=user --password=python --database=sampledb
    show variables like 'chara%';
    select * from sample;
    exit
    EOF
    docker-compose exec -T db bash <<EOF
    mysql --user=user --password=python --database=sampledb --default-character-set=utf8mb4
    show variables like 'chara%';
    select * from sample;
    exit
    EOF
    docker-compose run --rm python bash <<EOF
    cd /opt/project
    python -m venv env
    ./env/bin/python -m pip install mysql-connector-python PyMySQL
    cat >sample.py <<INNER_EOF
    import mysql.connector
    cnx = mysql.connector.connect(
        host='db',
        port='3306',
        user='user',
        password='python',
        database='sampledb',
        charset='utf8mb4'
    )
    cursor_=cnx.cursor()
    cursor_.execute("show variables like 'chara%';")
    rows = cursor_.fetchall()
    for row in rows:
        print (row)
    cursor_.execute("select * from sample;")
    rows = cursor_.fetchall()
    for row in rows:
        print (row)
    INNER_EOF
    cat >sample2.py <<INNER_EOF
    import pymysql.cursors
    cnx = pymysql.connect(
        host='db',
        port=3306,
        user='user',
        password='python',
        database='sampledb',
        charset='utf8mb4'
    )
    cursor_=cnx.cursor()
    cursor_.execute("show variables like 'chara%';")
    rows = cursor_.fetchall()
    for row in rows:
        print (row)
    cursor_.execute("select * from sample;")
    rows = cursor_.fetchall()
    for row in rows:
        print (row)
    INNER_EOF
    ./env/bin/python sample.py
    ./env/bin/python sample2.py
    EOF
    docker-compose down
    
[/code]

### 出力

[code]

    $ sh ../create_env.sh 
    Creating network "tmp_default" with the default driver
    Creating tmp_db_1 ... done
    mysql: [Warning] Using a password on the command line interface can be insecure.
    ERROR 1396 (HY000) at line 2: Operation CREATE USER failed for 'user'@'%'
    mysql: [Warning] Using a password on the command line interface can be insecure.
    Variable_name   Value
    character_set_client    latin1
    character_set_connection        latin1
    character_set_database  utf8mb4
    character_set_filesystem        binary
    character_set_results   latin1
    character_set_server    utf8mb4
    character_set_system    utf8mb3
    character_sets_dir      /usr/share/mysql-8.0/charsets/
    id      name
    1001    dockerを用いてpythonからmysqlに接続すると日本語が文字化けする
    1002    dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し
    1003    pythonからmysqlに接続しfetchallでテーブルを表示しようとすると
    1004                 
    mysql: [Warning] Using a password on the command line interface can be insecure.
    Variable_name   Value
    character_set_client    utf8mb4
    character_set_connection        utf8mb4
    character_set_database  utf8mb4
    character_set_filesystem        binary
    character_set_results   utf8mb4
    character_set_server    utf8mb4
    character_set_system    utf8mb3
    character_sets_dir      /usr/share/mysql-8.0/charsets/
    id      name
    1001    dockerã‚’ç”¨ã„ã¦pythonã‹ã‚‰mysqlã«æŽ¥ç¶šã™ã‚‹ã¨æ—¥æœ¬èªžãŒæ–‡å­—åŒ–ã‘ã™ã‚‹
    1002    dockerã‚’ç”¨ã„ã¦pythonã¨mysqlã®ã‚³ãƒ³ãƒ†ãƒŠã‚’ãã‚Œãžã‚Œä½œæˆã—
    1003    pythonã‹ã‚‰mysqlã«æŽ¥ç¶šã—fetchallã§ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’è¡¨ç¤ºã—ã‚ˆã†ã¨ã™ã‚‹ã¨
    1004    ðŸ¤§ ðŸ˜· ðŸ¤’ ðŸ¤• ðŸ¤‘ ðŸ¤  ðŸ˜ˆ ðŸ‘¿ ðŸ‘¹ ðŸ‘º ðŸ¤¡ ðŸ’© ðŸ‘» ðŸ’€
    Requirement already satisfied: mysql-connector-python in ./env/lib/python3.10/site-packages (8.0.31)
    Requirement already satisfied: PyMySQL in ./env/lib/python3.10/site-packages (1.0.2)
    Requirement already satisfied: protobuf<=3.20.1,>=3.11.0 in ./env/lib/python3.10/site-packages (from mysql-connector-python) (3.20.1)
    ('character_set_client', 'utf8mb4')
    ('character_set_connection', 'utf8mb4')
    ('character_set_database', 'utf8mb4')
    ('character_set_filesystem', 'binary')
    ('character_set_results', 'utf8mb4')
    ('character_set_server', 'utf8mb4')
    ('character_set_system', 'utf8mb3')
    ('character_sets_dir', '/usr/share/mysql-8.0/charsets/')
    ('1001', 'dockerã‚’ç”¨ã\x81„ã\x81¦pythonã\x81‹ã‚‰mysqlã\x81«æŽ¥ç¶šã\x81™ã‚‹ã\x81¨æ—¥æœ¬èªžã\x81Œæ–‡å\xad—åŒ–ã\x81‘ã\x81™ã‚‹')
    ('1002', 'dockerã‚’ç”¨ã\x81„ã\x81¦pythonã\x81¨mysqlã\x81®ã‚³ãƒ³ãƒ†ãƒŠã‚’ã\x81\x9dã‚Œã\x81žã‚Œä½œæˆ\x90ã\x81—')
    ('1003', 'pythonã\x81‹ã‚‰mysqlã\x81«æŽ¥ç¶šã\x81—fetchallã\x81§ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’è¡¨ç¤ºã\x81—ã‚ˆã\x81†ã\x81¨ã\x81™ã‚‹ã\x81¨')
    ('1004', 'ðŸ¤§ ðŸ˜· ðŸ¤’ ðŸ¤• ðŸ¤‘ ðŸ¤\xa0 ðŸ˜ˆ ðŸ‘¿ ðŸ‘¹ ðŸ‘º ðŸ¤¡ ðŸ’© ðŸ‘» ðŸ’€')
    ('character_set_client', 'utf8mb4')
    ('character_set_connection', 'utf8mb4')
    ('character_set_database', 'utf8mb4')
    ('character_set_filesystem', 'binary')
    ('character_set_results', 'utf8mb4')
    ('character_set_server', 'utf8mb4')
    ('character_set_system', 'utf8mb3')
    ('character_sets_dir', '/usr/share/mysql-8.0/charsets/')
    ('1001', 'dockerã‚’ç”¨ã\x81„ã\x81¦pythonã\x81‹ã‚‰mysqlã\x81«æŽ¥ç¶šã\x81™ã‚‹ã\x81¨æ—¥æœ¬èªžã\x81Œæ–‡å\xad—åŒ–ã\x81‘ã\x81™ã‚‹')
    ('1002', 'dockerã‚’ç”¨ã\x81„ã\x81¦pythonã\x81¨mysqlã\x81®ã‚³ãƒ³ãƒ†ãƒŠã‚’ã\x81\x9dã‚Œã\x81žã‚Œä½œæˆ\x90ã\x81—')
    ('1003', 'pythonã\x81‹ã‚‰mysqlã\x81«æŽ¥ç¶šã\x81—fetchallã\x81§ãƒ†ãƒ¼ãƒ–ãƒ«ã‚’è¡¨ç¤ºã\x81—ã‚ˆã\x81†ã\x81¨ã\x81™ã‚‹ã\x81¨')
    ('1004', 'ðŸ¤§ ðŸ˜· ðŸ¤’ ðŸ¤• ðŸ¤‘ ðŸ¤\xa0 ðŸ˜ˆ ðŸ‘¿ ðŸ‘¹ ðŸ‘º ðŸ¤¡ ðŸ’© ðŸ‘» ðŸ’€')
    Stopping tmp_db_1 ... done
    Removing tmp_db_1 ... done
    Removing network tmp_default
    $ 
    
[/code]

## 原因

不明。  
`character_set_system`がクライアント側の`default_character_set`と異なるためなのか、なぜかlatin1で処理された。

## 対策

my.cnfのコメントを外す

### 出力

[code]

    $ sh ../create_env.sh 
    Creating network "tmp_default" with the default driver
    Creating tmp_db_1 ... done
    mysql: [Warning] Using a password on the command line interface can be insecure.
    mysql: [Warning] Using a password on the command line interface can be insecure.
    Variable_name   Value
    character_set_client    utf8mb4
    character_set_connection        utf8mb4
    character_set_database  utf8mb4
    character_set_filesystem        binary
    character_set_results   utf8mb4
    character_set_server    utf8mb4
    character_set_system    utf8mb3
    character_sets_dir      /usr/share/mysql-8.0/charsets/
    id      name
    1001    dockerを用いてpythonからmysqlに接続すると日本語が文字化けする
    1002    dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し
    1003    pythonからmysqlに接続しfetchallでテーブルを表示しようとすると
    1004                 
    mysql: [Warning] Using a password on the command line interface can be insecure.
    Variable_name   Value
    character_set_client    utf8mb4
    character_set_connection        utf8mb4
    character_set_database  utf8mb4
    character_set_filesystem        binary
    character_set_results   utf8mb4
    character_set_server    utf8mb4
    character_set_system    utf8mb3
    character_sets_dir      /usr/share/mysql-8.0/charsets/
    id      name
    1001    dockerを用いてpythonからmysqlに接続すると日本語が文字化けする
    1002    dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し
    1003    pythonからmysqlに接続しfetchallでテーブルを表示しようとすると
    1004                 
    Collecting mysql-connector-python
      Downloading mysql_connector_python-8.0.31-cp310-cp310-manylinux1_x86_64.whl (23.5 MB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 23.5/23.5 MB 27.1 MB/s eta 0:00:00
    Collecting PyMySQL
      Downloading PyMySQL-1.0.2-py3-none-any.whl (43 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 43.8/43.8 kB 5.7 MB/s eta 0:00:00
    Collecting protobuf<=3.20.1,>=3.11.0
      Downloading protobuf-3.20.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.1 MB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.1/1.1 MB 12.6 MB/s eta 0:00:00
    Installing collected packages: PyMySQL, protobuf, mysql-connector-python
    Successfully installed PyMySQL-1.0.2 mysql-connector-python-8.0.31 protobuf-3.20.1
    ('character_set_client', 'utf8mb4')
    ('character_set_connection', 'utf8mb4')
    ('character_set_database', 'utf8mb4')
    ('character_set_filesystem', 'binary')
    ('character_set_results', 'utf8mb4')
    ('character_set_server', 'utf8mb4')
    ('character_set_system', 'utf8mb3')
    ('character_sets_dir', '/usr/share/mysql-8.0/charsets/')
    ('1001', 'dockerを用いてpythonからmysqlに接続すると日本語が文字化けする')
    ('1002', 'dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し')
    ('1003', 'pythonからmysqlに接続しfetchallでテーブルを表示しようとすると')
    ('1004', '             ')
    ('character_set_client', 'utf8mb4')
    ('character_set_connection', 'utf8mb4')
    ('character_set_database', 'utf8mb4')
    ('character_set_filesystem', 'binary')
    ('character_set_results', 'utf8mb4')
    ('character_set_server', 'utf8mb4')
    ('character_set_system', 'utf8mb3')
    ('character_sets_dir', '/usr/share/mysql-8.0/charsets/')
    ('1001', 'dockerを用いてpythonからmysqlに接続すると日本語が文字化けする')
    ('1002', 'dockerを用いてpythonとmysqlのコンテナをそれぞれ作成し')
    ('1003', 'pythonからmysqlに接続しfetchallでテーブルを表示しようとすると')
    ('1004', '             ')
    Stopping tmp_db_1 ... done
    Removing tmp_db_1 ... done
    Removing network tmp_default
    $ 
    
[/code]


CC BY-SA 4.0
2023-01-08T14:42:54.247
93253
2023-01-08T14:42:54.247
54957
93233
answer