2017-01-07 15 views
0

私はメモリに大きなファイル(> = 1ギガバイト)をコピーしたい:なぜPython 3xバッファがbash ddよりも大きいのですか?

#!/usr/bin/env python3 
# -*- coding: utf-8 -*- 

from subprocess import check_output 
from shlex import split 

zeroes = open('/dev/zero') 

SCALE = 1024 

B = 1 
KB = B * SCALE 
MB = KB * SCALE 
GB = MB * SCALE 

def ck(str): 
    print('{}:\n{}\n'.format(str, check_output(split('free -m')).decode())) 

ck('## Before') 

buffer = zeroes.read(GB) 

ck('## After') 

は出力:

## Before: 
       total  used  free  shared buff/cache available 
Mem:   15953  7080  6684   142  2188  8403 
Swap:   2047   0  2047 


## After: 
       total  used  free  shared buff/cache available 
Mem:   15953  9132  4632   142  2188  6351 
Swap:   2047   0  2047 

明らかに6684から4632 = 2052、ほぼ予想1の大きさ2倍をあるMB( GB)。問題は何

# mkdir -p /mnt/tmpfs/ 
# mount -t tmpfs -o size=1000G tmpfs /mnt/tmpfs/ 
# free -m 
       total  used  free  shared buff/cache available 
Mem:   15953  7231  6528   144  2192  8249 
Swap:   2047   0  2047 
# dd if=/dev/zero of=/mnt/tmpfs/big_file bs=1M count=1024 
1024+0 records in 
1024+0 records out 
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.695143 s, 1.5 GB/s 
# free -m 
       total  used  free  shared buff/cache available 
Mem:   15953  7327  5406  1168  3219  7129 
Swap:   2047   0  2047 

ddショー期待される結果と

テスト?なぜPythonが2倍大きいのでしょうか?

*をPython 3xに複製するベストプラクティスは何ですか?

*望ましい出力 - pythonは、ddと同じ量のメモリを使用します。

+0

Re: "desired output" - あなたの希望する出力は何ですか?巨大なストレージバッファをあらゆる言語で使用したい場合は、メモリマップされたIOを使用する方がよいでしょう。 –

+0

ところで、あなたのコンテンツがバイトテキストの代わりにUnicode文字列の場合は...あなたの問題があります。 –

+0

...バイトを読むには、 'zeroes = open( '/ dev/zero'、 'rb')'を使用してください。 –

答えて

1

How is unicode represented internally in Python?を参照してください。

ファイルがバイナリであることを指定していないため、ディスク上の単一バイトとして表されるコードポイントの場合でも、メモリ内に格納するために文字あたり2〜4バイトが必要なUnicode文字を読み取っています。


用途:

zeroes = open('/dev/zero', 'rb') # the 'b' flag is critical here! 

...バイト文字列を読み取るために、ファイルを開くために。

+0

Python 3.3のUnicode文字列でのPEP 393の実装は、内部的にさまざまな方法で表現されています。要件に応じて、1バイト、2バイト、または4バイトのシーケンスを使用して文字を格納できます([unicode api](https://docs.python.org/3/c-api/unicode.html))。これらは固定幅エンコーディングで、私はlatin-1、USC-2、UTF-32に対応していると思います。 '/ dev/zeros'を文字としてデコードするときは、2バイトまたは4バイトの表現を使う必要はありません。 latin-1を使用してデータを適切に保存することができます。試してみましょう: 's = '\ 0' *(1 << 20); print(sys.getsizeof(s)) 'を実行します。結果は1MB + 25バイトです。 – Dunes

関連する問題