TensorFlow ことはじめ

On 2015 年 11 月 12 日, in TensorFlow, by admin

TensorFlowが盛り上がっているので、早速使ってみた。 インストール方法は公式が詳しいので省略するとして、チュートリアルの最初のMNISTデータでの数字認識学習において、これはそのままプログラムを組めば良いのだが知らない人にははまるんではないかというポイントがあったのでメモ。

input_data.py

公式チュートリアルの、「ここにあるよ」と書かれているところからwgetするとhtmlで落ちてくるし、gitだと部分チェックアウトができないので、wgetで関連するファイルのみ取ってくる。

wget https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/g3doc/tutorials/mnist/input_data.py
wget http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
wget http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz 

後は公式の通り。

can’t determine number of CPU cores: assuming

 

自分はMac環境のバイナリをそのまま使用したが、Mac環境ならこれが返らないフローがあるように見えて実際はそこは通っていない…

この原因は、配布されているバイナリは少しバージョンが古いことによる。
github上の r6 以降を自分でビルドすればこの表示は出ない。
stackoverflow で python での解決法も出ているが、Session生成時の引数に誤りがあったので、正確な例を下記に示しておく。

これを使えば、どの環境でも警告は出なくなる。並列スレッド数に関しては個人の好みでご変更下さい。

import multiprocessing as mp
import tensorflow as tf
config=tf.ConfigProto(inter_op_parallelism_threads=mp.cpu_count(),
                      intra_op_parallelism_threads=mp.cpu_count())
sess = tf.Session(config=config)

なお、通常は対応プラットフォームであれば全コアを、そうでなければ4コアを使用するようにデフォルトでは設定されている。

そのため、他に動かすものがあるような場合等、使用コア数を制限したい場合も上記が使えるので、環境に応じてCPU負荷を調整したい場合にも使える。

Tagged with:  

Assemblaの利用方法

On 2012 年 10 月 5 日, in 未分類, by admin
 下記にアクセス
1.アカウント作成
既にGoogleやYahooのアカウントを持っている場合は、それらを使用してログイン。
それ以外はRegister以下の情報を入力してアカウントを作成。
2.専用ソフトのインストール
下記を参考にTortoiseSVNをインストールして下さい。
利用方法に関しては下記を参照。
3.チェックアウト
下記URLをチェックアウト
https://subversion.assembla.com/svn/プロジェクト名/
 

PyObjC の EPD へのインストール

On 2012 年 2 月 4 日, in python, by admin

PyObjC を EPD にインストールしようとしたところ、ちょっとしたコツがいたのでメモ。

事前に /usr/lib/libpython.dylib にリンクが当たらないようにファイル名を変更するなどの処置をとっておく。
/Library/Frameworks/Python.Framework, /System/Library/Frameworks/Python.Framework のパスも一時的に変更しておく。

その上で easy_install でまずパッケージをインストール。

sudo easy_install pyobjc-core pyobjc

そうすると、インストールは完了するものの、次のようなワーニングが出て

Modules/objc/fsref.m: In function ‘fsref_as_path’:
Modules/objc/fsref.m:73: warning: implicit declaration of function ‘PyMac_Error’
Modules/objc/fsref.m:73: warning: nested extern declaration of ‘PyMac_Error’

実行時には、次のようなImport Error が起こる。

ImportError: dlopen(/Library/Frameworks/EPD64.framework/Versions/7.2/lib/python2.7/site-packages/pyobjc_core-2.3-py2.7-macosx-10.5-x86_64.egg/objc/_objc.so, 2): Symbol not found: _PyMac_Error

また,同様に下記のエラーも出る。

ImportError: dlopen(/Library/Frameworks/EPD64.framework/Versions/7.2/lib/python2.7/site-packages/pyobjc_framework_Cocoa-2.3-py2.7-macosx-10.5-x86_64.egg/Foundation/_Foundation.so, 2): Symbol not found: _PyMac_GetOSType

nm で調べてみると、EPD の libpython2.7.dylib には PyMac_Error, PyMac_GetOSType が無い。

nm /Library/Frameworks/EPD64.framework/Versions/Current/lib/libpython2.7.dylib  | grep PyMac_Error

逆に,システム標準の python (2.7.1) や ports の python (2.7.2) には存在する。

nm /System/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib | grep PyMac_Error
00000000000b144d T _PyMac_Error
nm /opt/local/lib/libpython2.7.dylib | grep PyMac_Error
00000000000d5450 T _PyMac_Error

従って,EPD 独自の仕様が原因なようなので,fsref.m を直接修正すると動きそう。
そこで,まずは easy_install がインストールしている pyobjc-core のソースコードを下記URLからダウンロードする。

wget http://pypi.python.org/packages/source/p/pyobjc-core/pyobjc-core-2.3.tar.gz
wget http://pypi.python.org/packages/source/p/pyobjc-framework-Cocoa/pyobjc-framework-Cocoa-2.3.tar.gz

問題の Modules/fsref.m では、プリプロセッサで処理を分けているが、patchlevel.h で定義されている PY_MAJOR_VERSION は EPD も同じ 2 なため下記コードは PyMac_Errorを参照してしまい実際の処理では落ちる。

#if PY_MAJOR_VERSION == 2
    PyMac_Error(rc);
#else
    PyErr_Format(PyExc_OSError, "MAC Error %d", rc);
#endif

何か EPD で定義されている特別なプリプロセッサが無いか調べたが、見つけられなかったため、PyErr_Format を使用する方向で調整することに。
一応、PyErr_Format は nm コマンドで調べた結果、EPDの libpython2.7.dylib にも存在するので、PyErr_Format を使用するように上記コードを下記のように修正。

    PyErr_Format(PyExc_OSError, "MAC Error %d", rc);

次に、pyobjc-framework-Cocoa-2.3 の Modules/_Foundation_typecode.m にて、PyMac_GetOSType の関数宣言を有効化する。
さらに Modules/_AppKit_carbon.m の下記の部分を修正。

#if PY_MAJOR_VERSION == 2

#ifndef __LP64__

#include "pymactoolbox.h"

#else
	/* FIXME: the bits of pymactoolbox.h that we need,
	 * because said header doesn't work in 64-bit mode
	 */
extern PyObject *WinObj_New(WindowPtr);
extern int WinObj_Convert(PyObject *, WindowPtr *);
extern PyObject *WinObj_WhichWindow(WindowPtr);

#endif

全く薦められないやり方だが、WinObj_ConvertとWinObj_Newに関して、_Winmodule.c
を参考にして下記のように書き換える。

#if PY_MAJOR_VERSION == 2

#include "pymactoolbox.h"


/* Function to dispose a window, with a "normal" calling sequence */
static void
PyMac_AutoDisposeWindow(WindowPtr w)
{
    DisposeWindow(w);
}

PyTypeObject Window_Type;
#define WinObj_Check(x) ((x)->ob_type == &Window_Type || PyObject_TypeCheck((x), &Window_Type))

typedef struct WindowObject {
    PyObject_HEAD
    WindowPtr ob_itself;
    void (*ob_freeit)(WindowPtr ptr);
} WindowObject;

PyObject *WinObj_New(WindowPtr itself)
{
    WindowObject *it;
    if (itself == NULL) return PyErr_Format(PyExc_OSError, "MAC Error %d",resNotFound);
    /* XXXX Or should we use WhichWindow code here? */
    it = PyObject_NEW(WindowObject, &Window_Type);
    if (it == NULL) return NULL;
    it->ob_itself = itself;
    it->ob_freeit = NULL;
    if (GetWRefCon(itself) == 0)
    {
        //SetWRefCon(itself, (long)it);
        it->ob_freeit = PyMac_AutoDisposeWindow;
    }
    return (PyObject *)it;
}

int WinObj_Convert(PyObject *v, WindowPtr *p_itself)
{
    
    if (v == Py_None) { *p_itself = NULL; return 1; }
    if (PyInt_Check(v)) { *p_itself = (WindowPtr)PyInt_AsLong(v); return 1; }
    
    {
        DialogRef dlg;
        if (DlgObj_Convert(v, &dlg) && dlg) {
            *p_itself = GetDialogWindow(dlg);
            return 1;
        }
        PyErr_Clear();
    }
    if (!WinObj_Check(v))
    {
        PyErr_SetString(PyExc_TypeError, "Window required");
        return 0;
    }
    *p_itself = ((WindowObject *)v)->ob_itself;
    return 1;
}

static PyObject *Dlg_Error;

PyTypeObject Dialog_Type;

#define DlgObj_Check(x) ((x)->ob_type == &Dialog_Type || PyObject_TypeCheck((x), &Dialog_Type))

typedef struct DialogObject {
    PyObject_HEAD
    DialogPtr ob_itself;
} DialogObject;


int DlgObj_Convert(PyObject *v, DialogPtr *p_itself)
{
    if (v == Py_None) { *p_itself = NULL; return 1; }
    if (PyInt_Check(v)) { *p_itself = (DialogPtr)PyInt_AsLong(v);
        return 1; }
    if (!DlgObj_Check(v))
    {
        PyErr_SetString(PyExc_TypeError, "Dialog required");
        return 0;
    }
    *p_itself = ((DialogObject *)v)->ob_itself;
    return 1;
}

PyObject *DlgObj_New(DialogPtr itself)
{
    DialogObject *it;
    if (itself == NULL) { Py_INCREF(Py_None); return Py_None; }
    it = PyObject_NEW(DialogObject, &Dialog_Type);
    if (it == NULL) return NULL;
    it->ob_itself = itself;
    //SetWRefCon(GetDialogWindow(itself), (long)it);
    return (PyObject *)it;
}

この修正後に pyobjc-core-2.3, pyobjc-framework-Cocoa-2.3 双方を手動でインストール

sudo python setup.py install
 

Mac ports の動的ライブラリの再配布方法

On 2012 年 1 月 25 日, in 未分類, by admin

Mac ports で手に入る dylib を別環境で使用する際,依存関係が絶対パス指定になっていると別環境でも同様のパスを構成しなければならず、配布の際に面倒。

そこで、下記のようにしてdylib内部の依存関係のパスを書き換えることが可能。
これにより,Mac ports とかでコンパイルされた dylib とかも別環境で任意のパスで動かすことができる
例えば、libsndfile.dylibの依存関係は下記のように記述可能。


install_name_tool -change /opt/local/lib/libogg.0.dylib libogg.0.dylib libvorbisenc.2.dylib

install_name_tool で自分自身のIDを書き換える

install_name_tool -id libsndfile.1.dylib lib/darwin/libsndfile.1.dylib

dylib を読み込む時は、current working directory を dylib のパスに移動してから読み込むとOK

from os.path import join,dirname
from os import getcwd,chdir
import inspect
_curf=inspect.currentframe()
_modpath=dirname(_curf.f_code.co_filename)
from sys import platform
sndfile=None
if platform=='darwin':
librpath=join('lib','darwin')
cwd=getcwd(); chdir(join(_modpath,librpath))
sndfile=CDLL('libsndfile.1.dylib')
chdir(cwd)

ちなみに,dylibbundler というコマンドを使用すると,上記の作業を一括でやってくれるっぽいですね。

 

ちなみに、Kinect のスペックは下記の通りです。
これは PortAudio のデバッグ情報を使用して調べました。
SDKからWASAPIのサンプルを使用して調べても良かったのですが、その後の事を考えると面倒なので、今回は PortAudio を使うことにしました。

SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
Samples.wValidBitsPerSample=32
nChannels=4
nSamplesPerSec=16000
nBlockAlign=16

対応 API ですが、Windows のカーネルストリーミングは64bit環境では動きませんでした。内部のソースをデバッガで追ったのですが、デバイス自体は見つかるものの、指定したサンプルフォーマットが対応していないということで動きません。唯一、WASAPIのみで動くようになっているようです。

ちなみに、PortAudio++を使用するとこんな感じで初期化できます。

int N=4;
int fs=16000;
AutoSystem autoSys;
System &sys = System::instance();
// Set up the parameters required to open a (Callback)Stream:
HostApi& index = sys.hostApiByTypeId(paWASAPI);
portaudio::HostApi::DeviceIterator i ;
for(i=index.devicesBegin();i!=index.devicesEnd();i++){
if((*i).defaultSampleRate()==16000 && (*i).maxInputChannels()==4 && (*i).maxOutputChannels()==0 ) break ;
}
Device& dev=*i ;
DirectionSpecificStreamParameters inParams(dev,
N, FLOAT32,true,dev.defaultLowInputLatency(), NULL);
StreamParameters params( inParams,
DirectionSpecificStreamParameters::null(),
fs, 1024, paClipOff);
MemFunCallbackStream stream(params, record, callback);

注意すべきは、DirectionSpecificStreamParameters (これはCAPIでは AD変換器のpaStreamParametersの設定に当たります) の設定で,wav なんかにデータを落としたい時は interleaved 引数を true にすること。
もちろん、non-interleaved でも動きますが、データの書き込み時に時間方向とチャネル方向への書き込み方向が反転し、interleaved なデータの並びを仮定している wav フォーマットと inputBuffer 内部のデータの並びが合わなくなります。

逆に、リアルタイムアレイ処理をしたいのならば、ここを false に設定して non-interleaved を選ぶべきでしょう。チャネル毎にデータが分離されるので、後の処理が高速に実行できます。
詳細はここを参照して下さい。

callbackはいつも通りこんな感じです。

int callback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags)
{
return paContinue;
}

 

Kinect のマイクロホンアレイの構造

On 2011 年 7 月 2 日, in 未分類, by admin

内蔵されているマイクアレイはこんな感じの構造をしている。
これはKinectを真正面から見たときのアレイの構造。

一応、ノギスで測ったモノの、38mmは機体の誤差で40mmかも。意図的にやってるかどうかはわかりません。
マイク本体はこんな感じで、ゴム製のインシュレータに包まれています。
絶縁対策と、モーターの振動がマイクに拾われないようにするためでしょうか。

 

ばらしてみるとこんな感じです。

マイク本体は CZ034GU という単一指向性コンデンサマイクが使用されています。

本体の寸法など詳細なスペックはここを参考のこと。

これらのマイクは下図のように一つのコネクタにまとめられ、Kinectの本体基盤に接続されています。その先で,WM8737というプリアンプ内蔵AD変換器2台にそれぞれ二つつず接続されています。WM8737についてはここを参照。

本体側のコネクタはバランスになってるんですが、マイク側でCOLDをGNDに落としてるんでしょうね。マイク付近の線の変な盛り上がりはそのためかと。なので、全体はアンバランスで駆動しています。

もしKinectのマイクアレイの音質を上げたいなら、この構造なら一応は色んなマイクに換装はできるようです。

 

PySide でタスクトレイアプリケーション作成

On 2011 年 4 月 26 日, in python, Qt, by admin

研究室のソフトウェア管理の関係で作成しなければならなくなったので、覚え書き.
QtGui.QSystemTrayIcon を使用する.

PyQt4 でもほぼ一緒.

# coding:utf-8
from PySide import QtCore, QtGui, QtUiTools
from PySide.QtCore import SLOT,SIGNAL
import sys

class Window(QtGui.QDialog):
    def __init__(self,parent=None):
        super(Window,self).__init__(parent)
       
        self.quitAction = QtGui.QAction("&Quit",self)
        self.connect(self.quitAction,SIGNAL('triggered()'),QtGui.qApp,SLOT('quit()'))
        self.quitAction.triggered.connect(QtGui.qApp.quit)
       
        self.trayIconMenu = QtGui.QMenu(self)
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QtGui.QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
        self.trayIcon.setIcon(QtGui.QIcon("heart.svg"))       
        self.trayIcon.show()
        return   

def _main():
    app = QtGui.QApplication(sys.argv)
    if not QtGui.QSystemTrayIcon.isSystemTrayAvailable():
        raise OSError("We couldn't detect any system tray on this system.")
   
    QtGui.QApplication.setQuitOnLastWindowClosed(False)
       
    window=Window()   
    return app.exec_()

if __name__ == "__main__" : _main()
 

windowsのインストール済みソフトを列挙

On 2011 年 4 月 8 日, in python, by admin

Python を使用して Windows のインストール済みソフトを列挙する時、意外と64bit に対応したコードが少なかったので載せておきます。
あと、もうそろそろ _winreg のページはいい加減消したほうがよいと思う・・・



#coding:utf-8

from win32api import RegOpenKeyEx,RegEnumKeyEx,RegQueryValueEx
from win32con import HKEY_LOCAL_MACHINE,KEY_READ
from platform import architecture

def getInstalledSoftwareList():
    softname = []
    softver = []
    ROOTS=['SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',]
    if int(architecture()[0][:2])==64:
        ROOTS.append('SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall')
    for ROOT in ROOTS:
        hkey=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                        ROOT,
                        0, KEY_READ )
        for subkey in RegEnumKeyEx(hkey):
            try:
                subkey=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                                    ROOT+'\\'+subkey[0],
                                    0, KEY_READ)
                softname.append(RegQueryValueEx(subkey,'DisplayName')[0])
                softver.append(RegQueryValueEx(subkey,'DisplayVersion')[0])
            except:
                pass    
    return softname,softver

def _main():
    print getInstalledSoftwareList()
    return

if __name__=="__main__" : _main()


 

意外に知られていないようなので、記事にします。
ssh 接続時に su して X11 を使用しようとすると、下記のようなエラーメッセージが出てコマンドが通りません。

X11 connection rejected because of wrong authentication.

で、この対処法ですが、xauth でごにょごにょしても良いのですが、もっと簡単な方法があります。su コマンドの代わりに xsu コマンドを使用することです。

Debian では xsu は aptitude でインストールできます。

aptitude install xsu

 

PySerialがWin64で動かない場合の対処法

On 2011 年 1 月 7 日, in python, by admin

EPD付属の PySerial 2.5 が 64bit windows 環境で動かない。

raise SerialException(“WriteFile failed (%s)” % ctypes.WinError()) serial.serialutil.SerialException: WriteFile failed ([Error 6] ハンドルが無効です。)

同様のバグもここで報告されているよう。

これの問題は、シリアルポートを開く際に内部で呼び出している win32.CreateFile が返すハンドルが 32bit であるということ。

というわけで、python-win32 モジュールを調べてみると win32.CreateFile ではなく、win32file.CreateFile を呼び出せば 64bit ハンドルを取得できる模様。

というわけで、site-packages\serial\serialwin32.py の先頭で

import win32file
import win32con

として、

CreateFile, SetupComm, GetCommTimeouts, CloseHandle, SetCommTimeouts, SetCommMask, GetCommState, PurgeComm, etc…
などのwin32モジュールに依存している部分を書き換える。

あと、win32 で良くあるエラーコード取得のための返礼値占領問題も、win32file モジュール中ではポインタ渡しを一部返礼値に変更しているので、ここの部分も修正が必要。

修正にはこのサイトが役立つ。

http://tgolden.sc.sabren.com/pywin32-docs/win32.html

以下、修正後のソース

#! python
# Python Serial Port Extension for Win32, Linux, BSD, Jython
# serial driver for win32
# see __init__.py
#
# (C) 2001-2009 Chris Liechti <cliechti@gmx.net>
# this is distributed under a free software license, see license.txt
#
# Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>

import ctypes
import win32
import win32file
import win32con
import pywintypes

from serialutil import *


def device(portnum):
    """Turn a port number into a device name"""
    return 'COM%d' % (portnum+1) # numbers are transformed to a string


class Win32Serial(SerialBase):
    """Serial port implementation for Win32 based on ctypes."""

    BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
                 9600, 19200, 38400, 57600, 115200)

    def __init__(self, *args, **kwargs):
        self.hComPort = None
        SerialBase.__init__(self, *args, **kwargs)

    def open(self):
        """Open port with current settings. This may throw a SerialException
           if the port cannot be opened."""
        if self._port is None:
            raise SerialException("Port must be configured before it can be used.")
        # the "\\.\COMx" format is required for devices other than COM1-COM8
        # not all versions of windows seem to support this properly
        # so that the first few ports are used with the DOS device name
        port = self.portstr
        try:
            if port.upper().startswith('COM') and int(port[3:]) > 8:
                port = '\\\\.\\' + port
        except ValueError:
            # for like COMnotanumber
            pass
        self.hComPort = win32file.CreateFile(port,
               win32con.GENERIC_READ | win32con.GENERIC_WRITE,
               0, # exclusive access
               None, # no security
               win32con.OPEN_EXISTING,
               win32con.FILE_ATTRIBUTE_NORMAL | win32con.FILE_FLAG_OVERLAPPED,
               0)
        if self.hComPort == win32.INVALID_HANDLE_VALUE:
            self.hComPort = None    # 'cause __del__ is called anyway
            raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))

        # Setup a 4k buffer
        win32file.SetupComm(self.hComPort, 4096, 4096)

        # Save original timeout values:
        tos = win32file.GetCommTimeouts(self.hComPort)
        self._orgTimeouts = win32.COMMTIMEOUTS(*tos)
        self._rtsState = win32.RTS_CONTROL_ENABLE
        self._dtrState = win32.DTR_CONTROL_ENABLE

        self._reconfigurePort()

        # Clear buffers:
        # Remove anything that was there
        win32file.PurgeComm(self.hComPort,
                            win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
                            win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)

        self._overlappedRead = pywintypes.OVERLAPPED()
        self._overlappedRead.hEvent = win32.CreateEvent(None, 1, 0, None)
        self._overlappedWrite = pywintypes.OVERLAPPED()
        #~ self._overlappedWrite.hEvent = win32.CreateEvent(None, 1, 0, None)
        self._overlappedWrite.hEvent = win32.CreateEvent(None, 0, 0, None)
        self._isOpen = True

    def _reconfigurePort(self):
        """Set communication parameters on opened port."""
        if not self.hComPort:
            raise SerialException("Can only operate on a valid port handle")

        # Set Windows timeout values
        # timeouts is a tuple with the following items:
        # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
        #  ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
        #  WriteTotalTimeoutConstant)
        if self._timeout is None:
            timeouts = (0, 0, 0, 0, 0)
        elif self._timeout == 0:
            timeouts = (win32.MAXDWORD, 0, 0, 0, 0)
        else:
            timeouts = (0, 0, int(self._timeout*1000), 0, 0)
        if self._timeout != 0 and self._interCharTimeout is not None:
            timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]

        if self._writeTimeout is None:
            pass
        elif self._writeTimeout == 0:
            timeouts = timeouts[:-2] + (0, win32.MAXDWORD)
        else:
            timeouts = timeouts[:-2] + (0, int(self._writeTimeout*1000))
        win32file.SetCommTimeouts(self.hComPort, timeouts)

        win32file.SetCommMask(self.hComPort, win32.EV_ERR)

        # Setup the connection info.
        # Get state and modify it:
        comDCB = win32file.GetCommState(self.hComPort)
        comDCB.BaudRate = self._baudrate

        if self._bytesize == FIVEBITS:
            comDCB.ByteSize     = 5
        elif self._bytesize == SIXBITS:
            comDCB.ByteSize     = 6
        elif self._bytesize == SEVENBITS:
            comDCB.ByteSize     = 7
        elif self._bytesize == EIGHTBITS:
            comDCB.ByteSize     = 8
        else:
            raise ValueError("Unsupported number of data bits: %r" % self._bytesize)

        if self._parity == PARITY_NONE:
            comDCB.Parity       = win32.NOPARITY
            comDCB.fParity      = 0 # Disable Parity Check
        elif self._parity == PARITY_EVEN:
            comDCB.Parity       = win32.EVENPARITY
            comDCB.fParity      = 1 # Enable Parity Check
        elif self._parity == PARITY_ODD:
            comDCB.Parity       = win32.ODDPARITY
            comDCB.fParity      = 1 # Enable Parity Check
        elif self._parity == PARITY_MARK:
            comDCB.Parity       = win32.MARKPARITY
            comDCB.fParity      = 1 # Enable Parity Check
        elif self._parity == PARITY_SPACE:
            comDCB.Parity       = win32.SPACEPARITY
            comDCB.fParity      = 1 # Enable Parity Check
        else:
            raise ValueError("Unsupported parity mode: %r" % self._parity)

        if self._stopbits == STOPBITS_ONE:
            comDCB.StopBits     = win32.ONESTOPBIT
        elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
            comDCB.StopBits     = win32.ONE5STOPBITS
        elif self._stopbits == STOPBITS_TWO:
            comDCB.StopBits     = win32.TWOSTOPBITS
        else:
            raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)

        comDCB.fBinary          = 1 # Enable Binary Transmission
        # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
        if self._rtscts:
            comDCB.fRtsControl  = win32.RTS_CONTROL_HANDSHAKE
        else:
            comDCB.fRtsControl  = self._rtsState
        if self._dsrdtr:
            comDCB.fDtrControl  = win32.DTR_CONTROL_HANDSHAKE
        else:
            comDCB.fDtrControl  = self._dtrState
        comDCB.fOutxCtsFlow     = self._rtscts
        comDCB.fOutxDsrFlow     = self._dsrdtr
        comDCB.fOutX            = self._xonxoff
        comDCB.fInX             = self._xonxoff
        comDCB.fNull            = 0
        comDCB.fErrorChar       = 0
        comDCB.fAbortOnError    = 0
        comDCB.XonChar          = XON
        comDCB.XoffChar         = XOFF
        win32file.SetCommState(self.hComPort, comDCB)

    #~ def __del__(self):
        #~ self.close()

    def close(self):
        """Close port"""
        if self._isOpen:
            if self.hComPort:
                # Restore original timeout values:
                win32file.SetCommTimeouts(self.hComPort, self._orgTimeouts)
                # Close COM-Port:
                win32file.CloseHandle(self.hComPort)
                win32file.CloseHandle(self._overlappedRead.hEvent)
                win32file.CloseHandle(self._overlappedWrite.hEvent)
                self.hComPort = None
            self._isOpen = False

    def makeDeviceName(self, port):
        return device(port)

    #  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -

    def inWaiting(self):
        """Return the number of characters currently in the input buffer."""
        flags = win32.DWORD()
        comstat = win32.COMSTAT()
        if not win32file.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
            raise SerialException('call to ClearCommError failed')
        return comstat.cbInQue

    def read(self, size=1):
        """Read size bytes from the serial port. If a timeout is set it may
           return less characters as requested. With no timeout it will block
           until the requested number of bytes is read."""
        if not self.hComPort: raise portNotOpenError
        if size > 0:
            win32.ResetEvent(self._overlappedRead.hEvent)
            if not win32file.ClearCommError(self.hComPort):
                raise SerialException('call to ClearCommError failed')
            if self.timeout == 0:
                n = min(comstat.cbInQue, size)
                if n > 0:
                    rc,buf = win32file.ReadFile(self.hComPort, n, self._overlappedRead)
                    if win32.GetLastError() != win32.ERROR_IO_PENDING:
                        raise SerialException("ReadFile failed (%s)" % ctypes.WinError())
                    err = win32.WaitForSingleObject(self._overlappedRead.hEvent, win32.INFINITE)
                    read = buf[:rc]
                else:
                    read = bytes()
            else:
                rc,buf = win32file.ReadFile(self.hComPort, size, self._overlappedRead)
                rc = win32file.GetOverlappedResult(self.hComPort, self._overlappedRead, True)
                read = buf[:rc]
        else:
            read = bytes()
        return bytes(read)

    def write(self, data):
        """Output the given string over the serial port."""
        if not self.hComPort: raise portNotOpenError
        #~ if not isinstance(data, (bytes, bytearray)):
            #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
        # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
        if data:
            #~ win32event.ResetEvent(self._overlappedWrite.hEvent)
            err,n = win32file.WriteFile(self.hComPort, data, self._overlappedWrite)
            if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
                raise SerialException("WriteFile failed (%s)" % ctypes.WinError())
            # Wait for the write to complete.
            #~ win32.WaitForSingleObject(self._overlappedWrite.hEvent, win32.INFINITE)
            n = win32file.GetOverlappedResult(self.hComPort, self._overlappedWrite, True)
            if n != len(data):
                raise writeTimeoutError
            return n
        else:
            return 0


    def flushInput(self):
        """Clear input buffer, discarding all that is in the buffer."""
        if not self.hComPort: raise portNotOpenError
        win32.PurgeComm(self.hComPort, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)

    def flushOutput(self):
        """Clear output buffer, aborting the current output and
        discarding all that is in the buffer."""
        if not self.hComPort: raise portNotOpenError
        win32.PurgeComm(self.hComPort, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)

    def sendBreak(self, duration=0.25):
        """Send break condition. Timed, returns to idle state after given duration."""
        if not self.hComPort: raise portNotOpenError
        import time
        win32.SetCommBreak(self.hComPort)
        time.sleep(duration)
        win32.ClearCommBreak(self.hComPort)

    def setBreak(self, level=1):
        """Set break: Controls TXD. When active, to transmitting is possible."""
        if not self.hComPort: raise portNotOpenError
        if level:
            win32.SetCommBreak(self.hComPort)
        else:
            win32.ClearCommBreak(self.hComPort)

    def setRTS(self, level=1):
        """Set terminal status line: Request To Send"""
        if not self.hComPort: raise portNotOpenError
        if level:
            self._rtsState = win32.RTS_CONTROL_ENABLE
            win32.EscapeCommFunction(self.hComPort, win32.SETRTS)
        else:
            self._rtsState = win32.RTS_CONTROL_DISABLE
            win32.EscapeCommFunction(self.hComPort, win32.CLRRTS)

    def setDTR(self, level=1):
        """Set terminal status line: Data Terminal Ready"""
        if not self.hComPort: raise portNotOpenError
        if level:
            self._dtrState = win32.DTR_CONTROL_ENABLE
            win32.EscapeCommFunction(self.hComPort, win32.SETDTR)
        else:
            self._dtrState = win32.DTR_CONTROL_DISABLE
            win32.EscapeCommFunction(self.hComPort, win32.CLRDTR)

    def _GetCommModemStatus(self):
        stat = win32.DWORD()
        win32.GetCommModemStatus(self.hComPort, ctypes.byref(stat))
        return stat.value

    def getCTS(self):
        """Read terminal status line: Clear To Send"""
        if not self.hComPort: raise portNotOpenError
        return win32.MS_CTS_ON & self._GetCommModemStatus() != 0

    def getDSR(self):
        """Read terminal status line: Data Set Ready"""
        if not self.hComPort: raise portNotOpenError
        return win32.MS_DSR_ON & self._GetCommModemStatus() != 0

    def getRI(self):
        """Read terminal status line: Ring Indicator"""
        if not self.hComPort: raise portNotOpenError
        return win32.MS_RING_ON & self._GetCommModemStatus() != 0

    def getCD(self):
        """Read terminal status line: Carrier Detect"""
        if not self.hComPort: raise portNotOpenError
        return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0

    # - - platform specific - - - -

    def setXON(self, level=True):
        """Platform specific - set flow state."""
        if not self.hComPort: raise portNotOpenError
        if level:
            win32.EscapeCommFunction(self.hComPort, win32.SETXON)
        else:
            win32.EscapeCommFunction(self.hComPort, win32.SETXOFF)

    def outWaiting(self):
        """return how many characters the in the outgoing buffer"""
        flags = win32.DWORD()
        comstat = win32.COMSTAT()
        if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
            raise SerialException('call to ClearCommError failed')
        return comstat.cbOutQue


# assemble Serial class with the platform specific implementation and the base
# for file-like behavior. for Python 2.6 and newer, that provide the new I/O
# library, derive from io.RawIOBase
try:
    import io
except ImportError:
    # classic version with our own file-like emulation
    class Serial(Win32Serial, FileLike):
        pass
else:
    # io library present
    class Serial(Win32Serial, io.RawIOBase):
        pass


# Nur Testfunktion!!
if __name__ == '__main__':
    s = Serial(0)
    sys.stdout.write("%s\n" % s)

    s = Serial()
    sys.stdout.write("%s\n" % s)

    s.baudrate = 19200
    s.databits = 7
    s.close()
    s.port = 0
    s.open()
    sys.stdout.write("%s\n" % s)