2016-09-05 10 views
1

バイナリコンテンツをPythonスクリプトに埋め込む方法を知りたいと思います。例えば、私は(画像、サウンド、...)の周りに外部ファイルを持っていたくない、私はこのコンテンツを私のpythonスクリプトの中に暮らしたい。Pythonスクリプトにリソースを埋め込む

のは、私はこの小さなスニペットだとしましょう、明確にするリトル例:

from StringIO import StringIO 
from PIL import Image, ImageFilter 

embedded_resource = StringIO(open("Lenna.png", "rb").read()) 
im = Image.open(embedded_resource) 
im.show() 

im_sharp = im.filter(ImageFilter.SHARPEN) 
im_sharp.show() 

あなたが見ることができるように、例では、外部ファイル 'Lenna.png'

enter image description here

を読んでいると質問

リソース(変数)として「Lenna.png」を埋め込む方法私のpythonスクリプトに。 Pythonを使ってこの単純なタスクを達成する最速の方法は何ですか?

+0

私が考えることができるのは、画像を「生の」データに変換し、それを変数に格納することだけです。 – UnholySheep

答えて

1

Hereは最初のシナリオでは、外部ファイルに

を埋め込む例です、あなたもこのような何か、(デ)コードに絵をbase64を使用することができますあなたのプログラムのリソース。これを使用するには、埋め込みたいファイルへのパスを使用してpackageメソッドを呼び出します。クラスは、既にクラス内にあるものを置き換えるために使用するDATA属性を出力します。あらかじめ構築されたデータにファイルを追加する場合は、代わりにaddメソッドを使用してください。プログラムでクラスを使用するには、コンテキストマネージャ構文を使用してloadメソッドを呼び出します。返される値は、Pathオブジェクトで、他の関数のファイル名引数として、または再構成されたファイルを直接読み込むために使用できます。この使用例はSMTP Clientを参照してください。

import base64 
import contextlib 
import pathlib 
import pickle 
import pickletools 
import sys 
import zlib 


class Resource: 

    """Manager for resources that would normally be held externally.""" 

    WIDTH = 76 
    __CACHE = None 
    DATA = b'' 

    @classmethod 
    def package(cls, *paths): 
     """Creates a resource string to be copied into the class.""" 
     cls.__generate_data(paths, {}) 

    @classmethod 
    def add(cls, *paths): 
     """Include paths in the pre-generated DATA block up above.""" 
     cls.__preload() 
     cls.__generate_data(paths, cls.__CACHE.copy()) 

    @classmethod 
    def __generate_data(cls, paths, buffer): 
     """Load paths into buffer and output DATA code for the class.""" 
     for path in map(pathlib.Path, paths): 
      if not path.is_file(): 
       raise ValueError('{!r} is not a file'.format(path)) 
      key = path.name 
      if key in buffer: 
       raise KeyError('{!r} has already been included'.format(key)) 
      with path.open('rb') as file: 
       buffer[key] = file.read() 
     pickled = pickle.dumps(buffer, pickle.HIGHEST_PROTOCOL) 
     optimized = pickletools.optimize(pickled) 
     compressed = zlib.compress(optimized, zlib.Z_BEST_COMPRESSION) 
     encoded = base64.b85encode(compressed) 
     cls.__print(" DATA = b'''") 
     for offset in range(0, len(encoded), cls.WIDTH): 
      cls.__print("\\\n" + encoded[ 
       slice(offset, offset + cls.WIDTH)].decode('ascii')) 
     cls.__print("'''") 

    @staticmethod 
    def __print(line): 
     """Provides alternative printing interface for simplicity.""" 
     sys.stdout.write(line) 
     sys.stdout.flush() 

    @classmethod 
    @contextlib.contextmanager 
    def load(cls, name, delete=True): 
     """Dynamically loads resources and makes them usable while needed.""" 
     cls.__preload() 
     if name not in cls.__CACHE: 
      raise KeyError('{!r} cannot be found'.format(name)) 
     path = pathlib.Path(name) 
     with path.open('wb') as file: 
      file.write(cls.__CACHE[name]) 
     yield path 
     if delete: 
      path.unlink() 

    @classmethod 
    def __preload(cls): 
     """Warm up the cache if it does not exist in a ready state yet.""" 
     if cls.__CACHE is None: 
      decoded = base64.b85decode(cls.DATA) 
      decompressed = zlib.decompress(decoded) 
      cls.__CACHE = pickle.loads(decompressed) 

    def __init__(self): 
     """Creates an error explaining class was used improperly.""" 
     raise NotImplementedError('class was not designed for instantiation') 
+0

ありがとう!私は受け入れられた答えを変更しupvotedしました。私は他の答えを受け入れると本当に好きではありませんが、私の目的のためにあなたのものは本当に便利です – BPL

+0

自信を持って投票していただきありがとうございます!うまくいけば、参照プログラムはクラスの使い方の十分な例を提供します。リソースファイルをロードした後にリソースファイルを残したい場合は、 'load'メソッドで' delete = True'を 'delete = False'に変更するか、メソッドを呼び出して' False'をそのファイルに渡すことができます引数。このクラスの独創的な使い方は、プログラムに書いた他のモジュールを依存関係として必要とするように埋め込むことです。 SMTPクライアントは、 'tkinter'のクラスの周りにスレッドセーフなラッパーをロードできるようにします。全体的に、それはかなりうまくいった。 –

3

あなたの写真をPythonの文字列に変換し、別のファイル(resources.pyなど)に入れておけば、簡単に解析できます。

すべてのものを1つのバイナリに埋め込む場合は、py2exeのようなものを探しています。あなたは埋め込むための以下のクラスではなく便利かもしれません

import base64 
file = open('yourImage.png'); 
encoded = base64.b64encode(file.read()) 
data = base64.b64decode(encoded) # Don't forget to file.close() ! 
+1

Av4t4r私は[base64](http://kb.worldviz.com/articles/878)のソリューションをすぐに投稿しようとしていました。ええ、それは私が探していたものです、ありがとう。 – BPL

関連する問題