2017年08月11日

CentOS7でPython3.6をyumでインストールする

ソースからいつもインストールしていたが、面倒くさくなってきたのでyumでインストールする方法を調べた。

IUS Community ProjectというRHELやCentOS向けに、最新のソフトウェアのRPMを提供しているリポジトリを登録。

yum install -y https://centos7.iuscommunity.org/ius-release.rpm

リポジトリが登録出来たらyumでインストール。

yum install -y python36u python36u-devel python36u-libs python36u-pip python36u-setuptools python36u-tools

後でpip使うときに必要になるので、下記もインストールしておく。

sudo yum groupinstall "Development Tools"

Version確認。

python3.6 -V
pip3.6 -V
参考
  • CentOS7にPython3.4をインストールする[記事]
タグ:CentOS Python
posted by MINE at 18:47 | Comment(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2016年12月25日

CentOS7且つPython3でGeoIP2を使用する

環境はCentOS7.3で、Python3.4.3で確認した。

まずMAX MIND社[GeoLite2]からGeoLite2データベースを取得する。

wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz

gzipで圧縮されているので解凍する。

gunzip -d GeoLite2-City.mmdb.gz

続いて、PythonのGeoIPライブラリをインストールする。

/usr/local/python-3.4/bin/pip install geoip2

後は、Pythonでgeoip2.databaseをimportして使用する。
一先ずClassにして必要そうな値を返すサンプルを作成。

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
#
import sys
import geoip2.database

class GeoIP:
	def __init__(self):
		self.reader=geoip2.database.Reader('GeoLite2-City.mmdb')
	def getGeoLocation(self,ip):
		record = self.reader.city(ip)
		return(record.country.name,record.city.name,record.country.iso_code,record.location.latitude,record.location.longitude)


if __name__== "__main__":
	if len(sys.argv) == 2:              
		ipadress = sys.argv[1]
	else:
                ipadress = '8.8.8.8'
        
	geodata = GeoIP()
        print(geodata.getGeoLocation(ipadress)[0])
        print(geodata.getGeoLocation(ipadress)[1])
        print(geodata.getGeoLocation(ipadress)[2])
        print(geodata.getGeoLocation(ipadress)[3])
        print(geodata.getGeoLocation(ipadress)[4])

IPアドレス8.8.8.8で実行した結果は下記のようになる。

United States
Mountain View
US
37.386
-122.0838

サンプルには含めていないものもあるが、それぞれの変数は下記のようになる。

変数 意味
record.continent.name 大陸名 North America
record.continent.code 大陸コード NA
record.country.name 国名 United States
record.country.iso_code 国名コード US
record.subdivisions.most_specific.name 州・県 California
record.subdivisions.most_specific.iso_code 州・県コード CA
record.city.name 都市名 Mountain View
record.location.latitude 都市の緯度 37.386
record.location.longitude 都市の経度 -122.0838
record.location.time_zone 都市のタイムゾーン America/Los_Angeles

日本語のデータベース

mmdbを下記のように読むと、日本語のデータベースを読み込んでくれる。

self.reader=geoip2.database.Reader('GeoLite2-City.mmdb',['ja'])

8.8.8.8を調べると下記のように出力される。ただ、場所によっては日本語が無いようなので、英語のままの方が良い気がする。

アメリカ合衆国
マウンテンビュー
US
37.386
-122.0838
関連する記事
  • CentOS7にPython3.4をインストールする[記事]
  • pipを最新版にする[記事]
タグ:CentOS Python
posted by MINE at 15:36 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2016年05月05日

CentOS7にSphinx1.4.1をpython3でインストールする

ネットを見ていたら、やはりpython2.7で使っているケースが多かったが、インストールしたのがPython3.4なので、この環境でSphinxをインストールする。

結果論からいうと、特に困ったことは無かったけど。

Sphinxをインストール

/usr/local/python-3.4/bin/pip install sphinx

pythonコマンド以外パス通していなかったので、直接pip実行してインストール。

パスを通す

ln -s /usr/local/python-3.4/bin/sphinx-build /usr/local/bin/sphinx-build

sphinx-buildへのパスが通っていないので、そのまま実行するとmakeでコケる。
なのでパスを通す。

動作確認

sphinx-quickstartでプロジェクトを作成する。

# /usr/local/python-3.4/bin/sphinx-quickstart                                                                                       
Welcome to the Sphinx 1.4.1 quickstart utility.

Please enter values for the following settings (just press Enter to
accept a default value, if one is given in brackets).

Enter the root path for documentation.
> Root path for the documentation [.]: 
# ↑ドキュメントのルートパス省略時は今の場所

You have two options for placing the build directory for Sphinx output.
Either, you use a directory "_build" within the root path, or you separate
"source" and "build" directories within the root path.
> Separate source and build directories (y/n) [n]: 
# ↑ソースと、ビルド結果のフォルダを完全に分けるかどうか。
# デフォルトはソースのフォルダ内に_buildディレクトリができる。

Inside the root directory, two more directories will be created; "_templates"
for custom HTML templates and "_static" for custom stylesheets and other static
files. You can enter another prefix (such as ".") to replace the underscore.
> Name prefix for templates and static dir [_]: 
# ↑Sphinxの作るシステムディレクトリの名前の先頭に付く接頭辞。デフォルトは'_'

The project name will occur in several places in the built documentation.
> Project name: Hogehoge Project
> Author name(s): fuga
# ↑プロジェクト名と著者名。入力必須。

Sphinx has the notion of a "version" and a "release" for the
software. Each version can have multiple releases. For example, for
Python the version is something like 2.5 or 3.0, while the release is
something like 2.5.1 or 3.0a1.  If you don't need this dual structure,
just set both to the same value.
> Project version: 1.0.0.0
> Project release [1.0.0.0]: 
# ↑プロジェクトのバージョン。versionは荒く、releaseは細かい。
# versionは必須だけど、releaseはデフォルトでversionと同じものが入る。

If the documents are to be written in a language other than English,
you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.

For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.
> Project language [en]: ja
# ↑プロジェクトのサポート文字コード。後でPDF作るためにjaと入力した。

The file name suffix for source files. Commonly, this is either ".txt"
or ".rst".  Only files with this suffix are considered documents.
> Source file suffix [.rst]: 
# ↑ソースファイルのデフォルトの拡張子。デフォルトは.rst。

One document is special in that it is considered the top node of the
"contents tree", that is, it is the root of the hierarchical structure
of the documents. Normally, this is "index", but if your "index"
document is a custom template, you can also set this to another filename.
> Name of your master document (without suffix) [index]: 
# ↑ドキュメントのトップページ(マスター)のファイル名(拡張子なし)。デフォルトは'index'

Sphinx can also add configuration for epub output:
> Do you want to use the epub builder (y/n) [n]: y
# ↑EPUB用の設定ファイルを追加するか?後で試すのでyesにする。

Please indicate if you want to use one of the following Sphinx extensions:
> autodoc: automatically insert docstrings from modules (y/n) [n]: 
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: 
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: 
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: 
> coverage: checks for documentation coverage (y/n) [n]: 
> imgmath: include math, rendered as PNG or SVG images (y/n) [n]: 
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]: 
> ifconfig: conditional inclusion of content based on config values (y/n) [n]: 
> viewcode: include links to the source code of documented Python objects (y/n) [n]: 
> githubpages: create .nojekyll file to publish the document on GitHub pages (y/n) [n]: 
# ↑各種拡張機能をインストールするかどうか。必要なら後で追加できる。

A Makefile and a Windows command file can be generated for you so that you
only have to run e.g. `make html' instead of invoking sphinx-build
directly.
> Create Makefile? (y/n) [y]: 
> Create Windows command file? (y/n) [y]: 
# ↑ビルド用のMakefileとバッチファイルを作るかどうか。デフォルトは作成する。

Creating file ./conf.py.
Creating file ./index.rst.
Creating file ./Makefile.
Creating file ./make.bat.

Finished: An initial directory structure has been created.

You should now populate your master file ./index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

HTMLを生成して正しく動くか確認する。

make html

_build\html\の下にhtmlが生成される。
PDFやePubはまた別記事にする。

関連する記事

  • CentOS7にPython3.4をインストールする[記事]
  • pipを最新版にする [記事]
参考
タグ:CentOS Python Sphinx
posted by MINE at 01:42 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2016年05月04日

pipを最新版にする

以前ソースコードからコンパイルしてインストールしたpipが7.1.1で古かったのでアップデートする。
前回は/usr/local/python-3.4/にインストールしたので、その下にあるpipを叩いてアップデートを行う。

/usr/local/python-3.4/bin/pip install --upgrade pip

関連する記事

  • CentOS7にPython3.4をインストールする[記事]
タグ:CentOS Python
posted by MINE at 01:44 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2016年04月03日

CentOS7にPython3.4をインストールする

ビルド用のパッケージをインストールする。

yum install zlib-devel openssl-devel readline-devel ncurses-devel sqlite-devel expat-devel bzip2-devel tcl-devel tk-devel gdbm-devel

Pythonのパッケージをダウンロードする。

wget https://www.python.org/ftp/python/3.4.4/Python-3.4.4.tgz
tar -xvzf Python-3.4.4.tgz

Buildする。

./configure --prefix=/usr/local/python-3.4
make
make install

Pathを通す。

sudo ln -s /usr/local/python-3.4/bin/python3.4 /usr/local/bin/python
参考
  • LinuxでPythonをビルドするときの --enable-shared オプションについて[Qiita]
タグ:Python
posted by MINE at 20:53 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2015年04月30日

XMLを整形するプログラム

xmlのdiffを見ようと思ったら、改行もインデントも無いXMLだったので、
自分が見やすいようにxmlを整形するプログラムをpythonで作った。
動作確認はPython 3.4.3で実施。

コード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from xml.dom.minidom import parse, parseString
import codecs,sys,os

if __name__ == "__main__":
	param = sys.argv
	DestPath = os.path.dirname(param[1])

	dom = parse(param[1])
	with codecs.open(os.path.join(DestPath,'fix_' + os.path.basename(param[1])), 'bw') as f:
		f.write(dom.toprettyxml("\t","\n",encoding="utf-8"))
posted by MINE at 00:48 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2012年02月01日

ガラケーからGalaxy SII WiMAX(ISW11SC)のアドレス帳を移行するプログラム

ISW11SCを買った[記事]のだが、アドレス帳の移行で困ったのでプログラム作ってみた。SDカードで移せばって?それに気づいてたら、こんな記事読まなくても大丈夫だよ。

背景

ガラケー時代は、au oneアドレス帳[au]にバックアップをとるように同期してた。
Androidoに乗り換えたときも、これに同期すりゃいいじゃん!とか思ったら、このサービスはガラケー専用だった。

スマートフォンはどうすりゃいいんだ?と調べたら、au one Friends Note[au]というサービスがあって、Andoriodにもアプリが出てる[au]。
それで、このau one Friends Noteはau oneアドレス帳からインポートできる。

au one アドレス帳 → au one Friends Note → Galaxyと同期

で、移行できるじゃんか楽勝だねと思い、意気揚々とau one Friends Noteにインポート。完了したら、スマートフォンと同期ボタン押して、簡単なお仕事終了・・・とならなかった。

スマートフォンが同期する設定になっていません、とエラーメッセージ。
が、Galaxyのアプリを見ても、そんな設定変更するところが一切ない。
どういうこっちゃーと調べたら[ITmedia]

KDDIとJibe Mobileが、ソーシャルアドレス帳アプリ「au one Friends Note」の機能を1月26日15時から拡張する。<中略>対応機種はAndroid2.1以降のスマートフォンで、2012年春モデルと「AQUOS PHONE IS14SH」「ARROWS ES IS12F」は順次対応する。

春モデルまだ対応してねー。

というわけで、まだ同期できませんでした。

どうしようかなぁと考えたところ、au one friends Noteがエクスポート機能持ってて、Google contacts[google]がインポート機能持っているので、エクスポートしたものをGoogleが読み込める形にすればいいじゃんかと思って、カッとなって作った。

コード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys,os
import csv
from optparse import OptionParser

def convertPhoneType(data):
	return 'Mobile' if unicode(data, 'cp932').encode('utf8') == '携帯' else data

def convertMailType(data):
	return 'Home' if unicode(data, 'cp932').encode('utf8') == '自宅' else data
	
def convertCSV(filename,outputFileName):

	# 読み込みファイル
	csvfile = open(filename)
	auadress = csv.reader(csvfile)
	next(auadress) # 1行目はタイトルなので飛ばす
	
	# 出力ファイル
	filename = outputFileName
	writecsv = csv.writer(file(filename, 'w'), lineterminator='\n') # 書き込みファイルの設定
	writecsv.writerow(['Name','Given Name','Additional Name','Family Name','Yomi Name','Given Name Yomi','Additional Name Yomi','Family Name Yomi','Name Prefix','Name Suffix','Initials','Nickname','Short Name','Maiden Name','Birthday','Gender','Location','Billing Information','Directory Server','Mileage','Occupation','Hobby','Sensitivity','Priority','Subject','Notes','Group Membership','E-mail 1 - Type','E-mail 1 - Value','E-mail 2 - Type','E-mail 2 - Value','Phone 1 - Type','Phone 1 - Value','Phone 2 - Type','Phone 2 - Value'])
 
	for row in csv.reader(csvfile):
		print(row[265])
		writecsv.writerow([row[10],'','','',row[13],'','','','','','','','','','','','','','','','','','','','',row[20],row[0],convertMailType(row[268]),row[267],convertMailType(row[272]),row[271],convertPhoneType(row[266]),row[265],convertPhoneType(row[270]),row[269]])  # 1行(リスト)の書き込み
	 
	csvfile.close()

if __name__=='__main__':
	parser = OptionParser(version="0.5")
	parser.add_option("-o",
                     action="store",type="string",dest="filename",default=u'googleadress.csv',
                     help=u"The output file name is specified.",metavar="FILENAME")						 
	(options, args) = parser.parse_args()
	outputFileName = options.filename

	#引数がおかしい場合
	if len(sys.argv) < 2:
		print(u'Usage: # python',sys.argv[0],u'[sourcedirectorypath] -o "outputFile.csv"')
		quit()
	
	sourcePath = os.path.dirname(unicode(sys.argv[1],"mbcs") + '\\')

	if os.path.isfile(sourcePath) == False:	#存在しないFileを指定した場合
		print(u'The directory does not exist.',sourcePath)
		quit()
	else:
		convertCSV(sourcePath,outputFileName)

使い方

  1. au one friends Noteからエクスポートする。export.csvとする
  2. エクスポートしたcsvを上記プログラムにD&D
  3. ファイル名を指定しなければ、googleadress.csvが出力されるので、googleコンタクトからインポートする。

グループ、名前、携帯番号1,2、Eメールアドレス1,2、メモは移行できる。後は使わなかったら分からん。

posted by MINE at 00:08 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2011年09月25日

Pythonでプロファイラ使って性能測定する方法

cProfileを使う。[Python v2.6.2 documentation 27.4.Python プロファイラ
pythonに引数m(意味はライブラリのスクリプトを実行する)にcProfile渡して、実行したいプログラム名を渡す

python -m cProfile プログラム名

-sでソートが指定できる。timeとかcallとか使える。

python -m cProfile -s time プログラム名

-oでファイルに出力できるとヘルプに書いてあるが、出力しても何に使うのか不明。(プログラムの再利用できるの?)

python -m cProfile -o 出力ファイル名 プログラム名

人が見る分には下記の感じで、リダイレクトした方が良い気がする。

python -m cProfile プログラム名 > 出力ファイル名
posted by MINE at 20:09 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2011年09月11日

PILのTIFFはCCITT Group 3 Fax形式が扱えない

このプログラム[記事]で、縮小できない画像があり、「decoder tiff_ccitt not available」というエラーをはいていた。

ちょっと調べてみると、TIFFの圧縮形式には以下があり、PILは全部を扱えないようだ。

  • LZW:Lempel-Ziv & Welch algorithm
  • JPEG:Joint Photographic Expert Group
  • OJPEG:OLD JPEG
  • Pbit:Macintosh PackBits algorithm
  • 1D:CCITT Group 3 1-Dimensional Modified Huffman run length encoding
  • G3:CCITT Group 3 Fax, CCITT T.4 bi-level encoding
  • G4:CCITT Group 4 Fax, CCITT T.6 bi-level encoding
  • RLEw:CCITT run-length encoding, Word alignment
  • NeXT:NeXT 2bit encoding
  • TS4:ThunderScan 4bit run-length encoding
  • PKZIP:PKZIP-style Deflate encoding
  • ZIP
  • SGIl:SGI Log
  • SGIl2:SGI Log24

とりあえずテストした感じ、LZWは扱えそう。

posted by MINE at 22:42 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2011年09月04日

PythonはVisual Studioで

米Microsoft、Visual StudioでのPython開発をサポートするプラグイン「PTVS 1.0」をリリース[SOURCEFORGE]

MSからPythonをVSで開発できるようにするプラグインがリリース。

CPythonだけでなくIronPythonとかもできるようだ。

さっそく、会社に入れてみよう。

posted by MINE at 00:11 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

2011年06月20日

[Python] フォルダーとファイルをHTMLに出力するプログラム Ver1

仕事で仕様書に書くために、ファイルをリストアップするプログラムをちゃちゃっと書いたが、ちょっと機能不足だったので、家で書いてみた。
jsonモジュール使ってみたい!とか、家で使う際の機能を入れてみたりとか、欲望にまみれて書いたので、コードとは完全に別物になっちゃったけど。

コード

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# 指定された拡張子のみ、HTML形式(Table/List)で出力する
# fileNameDictに定義されているものは、置換する
from __future__ import print_function
import sys,os
import codecs
import json
from string import Template
from optparse import OptionParser

#リストアップ対象拡張子
ext_dic = [u'jpg']
#ファイル対比表のファイル名
dictFileName= u'filelistup_dict.json'

def isTarget(ext):
	return True if ext.lower() in ext_dic else False

def load_json(fname, encoding = 'utf-8'):
	with open(fname) as f:
		return json.load(f, encoding)

def writeHTML(sourcePath,table,outputHTMLTemplate):
	o=codecs.open( os.path.join(os.path.dirname(unicode(sys.argv[0],"mbcs")),outputFileName) ,'w','utf-8')
	o.write(outputHTMLTemplate.substitute({'dir': sourcePath.replace('\\', '/').split('/')[-1], 'files': table}))
	o.close()

def listupTable(sourcePath,fileNameDict,options):
	tableDirectoryTemplate = Template(u'\n\n${dir}\n\n\n')
	
	table=''
	uniqid=1
	for root, dirs, files in os.walk(sourcePath):
		(rootPath,fileName) = os.path.split(root)
		if options.isRelPath == True:
			table += tableDirectoryTemplate.substitute({'dir': os.path.relpath(root,os.path.split(sourcePath)[0])})
		else:
			table += tableDirectoryTemplate.substitute({'dir': root.replace(rootPath + u'\\',u'')})
		for file in files:
			if isTarget(file.split(".")[-1]) == True:
				line = u'{0}{1}
-
\n'.format(uniqid,fileNameDict.get(file,file)) table += line uniqid+=1 return table def listupList(sourcePath,fileNameDict,options): listDirectoryTemplate = Template(u'
  • ${dir}\n') list='' for root, dirs, files in os.walk(sourcePath): (rootPath,fileName) = os.path.split(root) if options.isRelPath == True: list += listDirectoryTemplate.substitute({'dir': os.path.relpath(root,os.path.split(sourcePath)[0])}) else: list += listDirectoryTemplate.substitute({'dir': root.replace(rootPath + u'\\',u'')}) list += u'
      ' for file in files: if isTarget(file.split(".")[-1]) == True: list += u'
    • '+ fileNameDict.get(file,file) + u'' list += u'
    \n\n' return list def listupFile(sourcePath,dictPath,options): if os.path.isfile(dictPath): fileNameDict = load_json(dictPath,'utf-8') else: fileNameDict = {} outputHTMLTemplate = Template(u'aaa') if options.isList == True: outputHTMLTemplate = Template(u'<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n\n\n\n\n\n\n
      ${files}
    \n\n') contents = listupList(sourcePath,fileNameDict,options) else: outputHTMLTemplate = Template(u'<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n\n\n\n\n\n\n\n${files}
    IDファイル名備考
    \n\n') contents = listupTable(sourcePath,fileNameDict,options) writeHTML(sourcePath,contents,outputHTMLTemplate) if __name__=='__main__': parser = OptionParser(version="0.5") parser.add_option("-o", action="store",type="string",dest="filename",default=u'filelist.html', help=u"The output file name is specified.",metavar="FILENAME") parser.add_option("-l","--List", action="store_true",dest="isList",default=False, help=u"The output file type is List Format.") parser.add_option("-r","--Enable relative filepath", action="store_true",dest="isRelPath",default=False, help=u"output rrelative path.") (options, args) = parser.parse_args() outputFileName = options.filename #引数がおかしい場合 if len(sys.argv) < 2: print(u'Usage: # python',sys.argv[0],u'[sourcedirectorypath] -r -l -o "outputFile.html"') quit() dictPath = os.path.join(os.path.split(sys.argv[0])[0],dictFileName) sourcePath = os.path.dirname(unicode(sys.argv[1],"mbcs") + '\\') if os.path.isdir(sourcePath) == False: #存在しないPathを指定した場合 print(u'The directory does not exist.',sourcePath) quit() else: listupFile(sourcePath,dictPath,options)
  • filelistup_dict.json

    pythonと同じ階層にファイル置いておくと、ファイル名を置き換えてくれる。
    まぁ、普段使うことは無いと思うけど。

    {
    	"test1.jpg":"ああああ",
    	"test2.jpg":"いいいい"
    }
    
    続きを読む
    posted by MINE at 01:06 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2011年05月07日

    [Python] 画像の縦横比を見て回転させ縮小するプログラム Ver7

    マルチプロセッシングはどうにも上手くいかないので、Ver5[記事]をベースに改良。
    アホみたいに2回もループしているのを1つにまとめたり、縮小する必要が無いのに、画像を再圧縮しているのを止めた。

    多少冗長な箇所があるけど、もう一回並列化にチャレンジするために残しておく。

    コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # 引数で指定したフォルダの画像ファイルを
    # 出力先フォルダに縮小・回転しながらコピーする
    
    from __future__ import print_function
    import os, sys,glob
    import shutil
    from PIL import Image
    
    # 出力先フォルダ指定。
    TARGET_DIR = u'C:\\Photo'
    #COWON A3向け
    #max_size = (800, 480)
    #PSP向け
    #max_size = (480, 270)
    #Ziio向け
    max_size = (480, 800)
    #対象拡張子
    ext_dic = ['.jpg','.jpeg','.png','.bmp']
    #ファイル名のprefix
    DEST_PREFIX = 's_'
    #JPEG品質
    JPEG_QUALITY = 75
    
    def makeOutputDirectory(outputDirPath):
    	if os.path.isdir(outputDirPath) == False:
    		os.makedirs(outputDirPath)
    
    def isTarget(ext):
    	return True if ext.lower() in ext_dic else False
    
    class ProgressBar:
    	def __init__(self,totalNum):
    		self.totalNum = totalNum
    		self.counter = 0
    		self.chr = u"*"
    		self.width = 40
    	def addCounter(self,incrementNum):
    		self.counter += incrementNum
    	def show(self):
    		pbar_chrs = self.chr * (self.width * self.counter / self.totalNum)
    		percentage = 100 * self.counter / self.totalNum
    		meter = u'\r|{0}{1}| {2}/{3}個 ({4}%)'.format(pbar_chrs,u' ' * (self.width - len(pbar_chrs)),self.counter,self.totalNum, percentage)
    		sys.stdout.write(meter)
    		sys.stdout.flush()
    
    def createTargetImagePath( path,targetBaseDirectory ):
    
    	targetPath = []
    	names = os.listdir(path)
    	targetDirectory = targetBaseDirectory
    
    	for name in names:
    		srcname = os.path.join(path, name)
    		try:
    			if os.path.isdir(srcname):
    				targetDirectory = os.path.join(targetBaseDirectory, name)
    				targetPath += createTargetImagePath( srcname,targetDirectory )
    			else:
    				root, ext = os.path.splitext(srcname)
    				if isTarget(ext) == True:
    					targetPath.append((srcname,os.path.join(targetDirectory,DEST_PREFIX + name)))
    		except (IOError, os.error), why:
    			print(u"Can't copy",srcname,u':',str(why))
    	return (targetPath)
    
    def shrinkImage(srcFileName, dstFileName):
    
    	sourceImage = Image.open(srcFileName)
    	
    	if sourceImage.size[0] > max_size[0] or sourceImage.size[1] > max_size[1] or sourceImage.format == 'BMP':
    		destImage = sourceImage
    		# BMPの場合、JPEGにする
    		if sourceImage.format == 'BMP':
    			destImage = destImage.convert('RGB')
    			root,ext = os.path.splitext(dstFileName)
    			dstFileName = root + '.jpg'
    		else:
    			format = sourceImage.format
    		
    		if max_size[0] > max_size[1]:
    			#横が長いディスプレイの場合は縦長の画像を回転させる。
    			if destImage.size[0] < destImage.size[1]:
    				destImage = destImage.rotate(270)
    		else:
    			#縦が長いディスプレイの場合は横長の画像を回転させる。
    			if destImage.size[0] > destImage.size[1]:
    				destImage = destImage.rotate(270)
    		destImage.thumbnail(max_size, Image.ANTIALIAS)
    		destImage.save(dstFileName,quality=JPEG_QUALITY)
    	else:
    		# 画面に収まらないor BMP形式以外の場合は、再圧縮する必要ないので普通のコピーにする
    		shutil.copy(srcFileName,dstFileName)
    	
    
    def copyImageTree(targetList,progress):
    
    	for target in targetList:
    		srcname = target[0]
    		dstname = target[1]
    		try:
    			makeOutputDirectory(os.path.dirname(dstname))
    			shrinkImage(srcname,dstname)
    			progress.addCounter(1)
    			progress.show()
    		except (IOError, os.error), why:
    			print(u"Cant' copy",srcname,'to',dstname,u':',str(why))
    	
    if __name__=='__main__':
    	#引数がおかしい場合
    	if len(sys.argv) < 2:
    		print(u'Usage: # Python ',sys.argv[0],u' [souceimagedirectorypath]...')
    		raw_input()
    		quit()
    		
    	targetPathList = []
    	for x in range(1,len(sys.argv)):
    		sourcePath = os.path.dirname(unicode(sys.argv[x],"mbcs") + '\\')
    
    		if os.path.isdir(sourcePath) == False:	#存在しないPathを指定した場合
    			print(u'[',sourcePath,u']: Src directory does not exist.')
    			raw_input()
    			quit()
    		elif os.path.isdir(TARGET_DIR) == False:	#存在しないPathを指定した場合
    			print(u'[',TARGET_DIR,u']: Dest directory does not exist.')
    			raw_input()
    			quit()
    		elif sourcePath == TARGET_DIR:	#入力先と出力先が同じ場合
    			print(u'The input destination is the same as the output destination.')
    			raw_input()
    			quit()
    		else:
    			targetPathList +=  createTargetImagePath(sourcePath,(TARGET_DIR + '\\' + os.path.basename(sourcePath)))
    	
    	if len(targetPathList) == 0:
    		print(u'File does not exist.')
    		quit()
    
    	progress = ProgressBar(len(targetPathList))
    	copyImageTree(targetPathList,progress)
    2011/5/8 20:46 追記
    タグ:Python
    posted by MINE at 23:58 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2011年04月03日

    mainで使用した値はローカルスコープじゃ無かったのか

    コマンドラインのオプション解析器を試していたら、 __main__で宣言した値が別の関数で使える事に気づいた。

    ネットで調べてみたら、「if __name__ == "__main__": 」って直接実行時はその後を実行するが、importしたときは実行されないためのガード条件だった。

    知らんかった。
    つい、C/C++のノリで考えてたよ・・・。

    そりゃ関数じゃないのならば、関数にスコープが閉じている訳ないよな。

    調査用コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    from __future__ import print_function
    import os, sys,glob
    from optparse import OptionParser
    
    def test2():
    	print(outputFileName)
    	x = 2
    	print(x)
    	
    def test1():
    	print(outputFileName)
    	x = 99
    	test2()
    	
    if __name__ == "__main__":
    	parser = OptionParser(version="0.2")
    	parser.add_option("-o",
                         action="store",
                         type="string",
                         dest="filename",
                         default=u'test.html',
                         help=u"The output file name is specified.",
                         metavar="FILENAME")		  
    	(options, args) = parser.parse_args()
    	outputFileName = options.filename
    	
    	test1()
    タグ:Python
    posted by MINE at 13:32 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2011年03月22日

    [Python] 画像の縦横比を見て回転させ縮小するプログラム Ver6α

    [記事]で挙げた問題点の標準出力のは、まだ良いアイディアが思いつかいないけど、とりあえずバックアップ目的で晒しておく。

    コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # 引数で指定したフォルダの画像ファイルを
    # 出力先フォルダに縮小・回転しながらコピーする
    
    from __future__ import print_function
    import os, sys,glob
    import multiprocessing
    from multiprocessing import Pool
    from PIL import Image
    
    # 出力先フォルダ指定。
    TARGET_DIR = u"E:\\test"
    #COWON A3向け
    #max_size = (800, 480)
    #PSP向け
    #max_size = (480, 270)
    #Ziio向け
    max_size = (480, 800)
    #対象拡張子
    ext_dic = [".jpg",".jpeg",".png",".bmp"]
    
    def makeOutputDirectory(outputDirPath):
    	if os.path.isdir(outputDirPath) == False:
    		os.mkdir(outputDirPath)
    
    def isTarget(ext):
    	return True if ext.lower() in ext_dic else False
    
    class ProgressBar:
    	def __init__(self,totalNum):
    		self.totalNum = totalNum
    		self.counter = 0
    		self.chr = u"*"
    		self.width = 40
    	def addCounter(self,incrementNum):
    		self.counter += incrementNum
    	def show(self):
    		pbar_chrs = self.chr * (self.width * self.counter / self.totalNum)
    		percentage = 100 * self.counter / self.totalNum
    		meter = u"\r|{0}{1}| {2}/{3}個 ({4}%)".format(pbar_chrs,u' ' * (self.width - len(pbar_chrs)),self.counter,self.totalNum, percentage)
    		sys.stdout.write(meter)
    		sys.stdout.flush()
    	
    def countImageFileNum( path ):
    
        counter = 0
        names = os.listdir(path)
    
        for name in names:
            srcname = os.path.join(path, name)
            try:
                if os.path.isdir(srcname):
                    counter += countImageFileNum( srcname )
                else:
          		    root, ext = os.path.splitext(srcname)
          		    if isTarget(ext) == True:
          		        counter += 1
            except (IOError, os.error), why:
    			print("Can't copy",srcname,":",str(why))
        return counter
    
    def shrinkImage(srcFileName, dstFileName):
    
    	sourceImage = Image.open(srcFileName)
    	destImage = sourceImage
    
    	if max_size[0] > max_size[1]:
    		#横が長いディスプレイの場合は縦長の画像を回転させる。
    		if destImage.size[0] < destImage.size[1]:
    			destImage = destImage.rotate(270)
    	else:
    		#縦が長いディスプレイの場合は横長の画像を回転させる。
    		if destImage.size[0] > destImage.size[1]:
    			destImage = destImage.rotate(270)
    	destImage.thumbnail(max_size, Image.ANTIALIAS)
    	destImage.save(dstFileName)
    
    def copyImageTree(src,dst,progress):
    
    	names = os.listdir(src)
    	makeOutputDirectory(dst)
    
    	for name in names:
    		srcname = os.path.join(src, name)
    		dstname = os.path.join(dst, name)
    		try:
    			if os.path.isdir(srcname):
    				copyImageTree(srcname, dstname,progress)
    			else:
    				root, ext = os.path.splitext(srcname)
    				if isTarget(ext) == True:
    					shrinkImage(srcname,dstname)
    					progress.addCounter(1)
    					progress.show()
    		except (IOError, os.error), why:
    			print(u"Cant' copy",srcname,u"to",dstname,u":",str(why))
    		
    def transferImage(sourcePath):
    	progress = ProgressBar(countImageFileNum(sourcePath))
    	copyImageTree(sourcePath,(TARGET_DIR + u"\\" + os.path.basename(sourcePath)),progress)
    	
    if __name__=='__main__':
    	#引数がおかしい場合
    	if len(sys.argv) < 2:
    		print(u"Usage: # Python ",sys.argv[0],u" [souceimagedirectorypath]...")
    		raw_input()
    		quit()
    		
    	targetPathList = []
    	for x in range(1,len(sys.argv)):
    		sourcePath = os.path.dirname(unicode(sys.argv[x],"mbcs") + '\\')
    
    		if os.path.isdir(sourcePath) == False:	#存在しないPathを指定した場合
    			print('[',soucePath,']: Src directory does not exist.')
    			raw_input()
    			quit()
    		elif os.path.isdir(TARGET_DIR) == False:	#存在しないPathを指定した場合
    			print('[',TARGET_DIR,']: Dest directory does not exist.')
    			raw_input()
    			quit()
    		elif sourcePath == TARGET_DIR:	#入力先と出力先が同じ場合
    			print('The input destination is the same as the output destination.')
    			raw_input()
    			quit()
    		else:
    			targetPathList.append(sourcePath)
    
    	processnum = multiprocessing.cpu_count() if ((len(sys.argv)-1) > multiprocessing.cpu_count()) else (len(sys.argv)-1)
    	pool = Pool(processes=processnum)
    	pool.map(transferImage,targetPathList)
    参考
    • [Python] 画像の縦横比を見て回転させ縮小するプログラム Ver5[記事]
    タグ:Python
    posted by MINE at 01:04 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2011年03月21日

    マルチプロセスのプログラミングはムズイ

    Python2.7にアップデートしたので、画像縮小するプログラム[明鏡止水]をマルチプロセスに対応させようと決意。
    自分の環境は、Core2QuadなのにGILの為に1CPUしか使われてなかったのが、何となく勿体なくて。

    んで、リソースの競合が起きにくいように、今まで引数を1つしか受け付けなかったものを複数のフォルダパスを渡せるようにして、それぞれ別のプロセスで動かすように改良。
    ここまでは簡単だったんだけど、問題は画面表示。

    大雑把で良いから進捗を表示させようと思ったんだけど、そもそも画面は1つ。縮小処理は最大4プロセス。ってことは、画面表示しているところに、処理の進み具合をプロセス間通信しなきゃいけないじゃん。ギャフン。
    この辺り、真面目に考えないと作れない。。。

    データ構造をちゃんと考えれば、共有メモリでもいけるのかな?

    タグ:Python
    posted by MINE at 01:52 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    [Python]コンソールのプログレスバー for Python2.7

    この数日で、Pythonを2.7にVerUpさせた。
    今まで使ってたプログレスバー[明鏡止水]はprint文だったが、python3では関数になってしまったので、このままでは動かない。
    後々困らないように、参考のサイトを見ながら、プログレスバーをちょっと書き換えて引っかからないように書き換えた。と言っても、Python3でテストしてないけど(おぃ

    コード

    class ProgressBar:
    	def __init__(self,totalNum):
    		self.totalNum = totalNum
    		self.counter = 0
    		self.chr = u"*"
    		self.width = 40
    	def addCounter(self,incrementNum):
    		self.counter += incrementNum
    	def show(self):
    		pbar_chrs = self.chr * (self.width * self.counter / self.totalNum)
    		percentage = 100 * self.counter / self.totalNum
    		meter = u"\r|{0}{1}| {2}/{3}個 ({4}%)".format(pbar_chrs,u' ' * (self.width - len(pbar_chrs)),self.counter,self.totalNum, percentage)
    		sys.stdout.write(meter)
    		sys.stdout.flush()
    
    参考
    • コンソール(ターミナル・シェル)上で改行をさせずに文字を表示する方法(タイマーを作ってみた) [hazimarino]
    タグ:Python
    posted by MINE at 01:06 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2011年01月12日

    Pythonでマルチコアを上手く利用するには?

    最近、小物のPythonプログラムを改修しているのだが、ちょっと大きいデータを渡すとCPUがBusyになる。
    が、タスクマネージャー見ると1コアしか使っていない。

    Threadingクラス使って、ちょこっとテストプログラム作ってみたが、あんまりコアを使ってくれない。

    調べてみたらGIL[InfoQ]の足かせで、マルチスレッドプログラムが遅くなるらしい。Python3.2で改善されるようだけど、3.2移行するならいっそIronPythonとかに移行したほうが幸せなんだろうか?

    タグ:Python
    posted by MINE at 00:47 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2010年02月03日

    [Python] 画像の縦横比を見て回転させ縮小するプログラム Ver5

    今日は家のメンテで、一日家にいたので、ちょっと遊んでた。

    縮小するプログラム[明鏡止水]を、サブディレクトリまで読むように変更した。
    参考にしたコードは、pythonライブラリのcopytree[python.jp]。

    しかし、こう細々アップデートしていると、管理がメンドイ。Google Codeのアカウント作ってみようかなぁ。

    コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # 引数で指定したフォルダの画像ファイルを
    # 出力先フォルダに縮小・回転しながらコピーする
    
    import os, sys,glob
    from PIL import Image
    
    # 出力先フォルダ指定。
    TARGET_DIR = u"C:\\PHOTO"
    #for COWON A3
    max_size = (800, 480)
    #for PSP
    #max_size = (480, 270)
    #対象拡張子
    ext_dic = [".jpg",".jpeg",".png",".bmp"]
    
    def makeOutputDirectory(outputDirPath): 
        if os.path.isdir(outputDirPath) == False:
            os.mkdir(outputDirPath)
    
    def isTarget(ext): 
        if ext.lower() in ext_dic:
            return True
        else:
            return False
    
    class ProgressBar:
        def __init__(self,totalNum):
            self.totalNum = totalNum
            self.counter = 0
            self.chr = u"*"
            self.width = 32
            self.bar_text_space = 4
        def addCounter(self,incrementNum):
            self.counter += incrementNum
        def show(self):
            pbar_chrs = self.chr * (self.width * self.counter / self.totalNum)
            percentage = 100 * self.counter / self.totalNum
            print u"\r|%-*s| %*d/%d個 (%3d%%)" % \
                (self.width, pbar_chrs, self.bar_text_space, self.counter,self.totalNum, percentage),
            sys.stdout.flush()
    
    def countImageFileNum( path ):
        counter = 0
        names = os.listdir(path)
    
        for name in names:
            srcname = os.path.join(path, name)
            try:
                if os.path.isdir(srcname):
                    counter += countImageFileNum( srcname )
                else:
                      root, ext = os.path.splitext(srcname)
                      if isTarget(ext) == True:
                          counter += 1
            except (IOError, os.error), why:
                print "Can't copy %s : %s" % (`srcname`, str(why))
        return counter
    
    def shrinkImage(srcFileName,dstFileName):
    
        sourceImage = Image.open(infile) 
        destImage = sourceImage 
        # 縦長の画像の場合、回転させる 
        if destImage.size[0] < destImage.size[1]: 
             destImage = destImage.rotate(270) 
        destImage.thumbnail(max_size, Image.ANTIALIAS) 
        destImage.save(os.path.join(outputDirPath,"s_" + os.path.basename(infile)))
    
    def copyImageTree(src,dst,progress):
    
        names = os.listdir(src)
        makeOutputDirectory(dst)
    
        for name in names:
            srcname = os.path.join(src, name)
            dstname = os.path.join(dst, name)
            try:
                if os.path.isdir(srcname):
                   copyImageTree(srcname, dstname,progress)
                else:
                    root, ext = os.path.splitext(srcname)
                    if isTarget(ext) == True:
                        shrinkImage(srcname,dstname)
                        progress.addCounter(1)
                        progress.show()
            except (IOError, os.error), why:
                print(u"Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why)))
    
    
    if __name__=='__main__':
        #引数の数がおかしい場合
        if len(sys.argv) != 2: 
            print('Usage: # python %s [SourceImageDirectoryPath]' % sys.argv[0])
            quit()
    
        sourcePath = os.path.dirname(unicode(sys.argv[1],"mbcs") + '\\')
    
        if os.path.isdir(sourcePath) == False: 
            print('[%s]: Src directory does not exist.' % sourcePath)
            quit()
        elif os.path.isdir(TARGET_DIR) == False: 
            print('[%s]: Dest directory does not exist.' % TARGET_DIR)
            quit()
        elif sourcePath == TARGET_DIR: 
            print('The input destination is the same as the output destination. ')
            quit()
        else: 
            progress = ProgressBar(countImageFileNum( sourcePath ))
            copyImageTree(sourcePath,(TARGET_DIR + u"\\" + os.path.basename(sourcePath)),progress)
    
    
    タグ:Python
    posted by MINE at 18:46 | Comment(0) | TrackBack(1) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2010年02月01日

    [Python] 画像の縦横比を見て回転させ縮小するプログラム Ver4

    画像転送するプログラム使ってたが[明鏡止水]、多数のファイルが入ってるフォルダを突っ込むといつ終わるか分からん!!!

    と思って、プログレスバー付けてみた。
    あんまテストしていないけど、動きそうなので更新。

    後は、複数フォルダも対応させようかなぁ。

    コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # 引数で指定したフォルダの画像ファイルを
    # 出力先フォルダに縮小・回転しながらコピーする
    
    import os, sys,glob
    from PIL import Image
    
    # 出力先フォルダ指定。
    TARGET_DIR = u"C:\\PHOTO"
    #COWON A3向け
    max_size = (800, 480)
    #PSP向け
    #max_size = (480, 270)
    #対象拡張子
    ext_dic = [".jpg",".jpeg",".png",".bmp"]
    #プログレスバーの設定
    progress_bar_width = 32
    progress_bar_text_space = 4
    progress_bar_chr = "*"
    
    def getOutputDirectoryName(sourcePath):
        dirName = os.path.split(sourcePath)
        return dirName[1]
    
    def makeOutputDirectory(outputDirPath): 
        if os.path.isdir(outputDirPath) == False:
            os.mkdir(outputDirPath)
    
    def isTarget(ext): 
        if ext.lower() in ext_dic:
            return True
        else:
            return False
    
    def show_progress_bar(pbar_chr, pbar_width, total, current_num):
        pbar_chrs = pbar_chr * (pbar_width * current_num / total)
        percentage = 100 * current_num / total
        print u"\r|%-*s| %*d/%d個 (%3d%%)" % \
            (pbar_width, pbar_chrs, progress_bar_text_space, current_num, total, percentage),
        sys.stdout.flush()
    
    def countFileNum( path ):
        counter = 0
        for file in os.listdir( path ):
            if os.path.isdir( path + file ) == False:
                root, ext = os.path.splitext(file)
                if isTarget(ext) == True:
                    counter += 1
        return counter
    
    def shrinkImage(sourcePath):
    
        outputDirPath = os.path.join(TARGET_DIR, getOutputDirectoryName(sourcePath))
        makeOutputDirectory(outputDirPath)
    
        total = countFileNum( sourcePath )
        count = 0
        for infile in glob.glob(os.path.join(sourcePath,"*.*")):
            root, ext = os.path.splitext(infile) 
            if isTarget(ext) == True:
                sourceImage = Image.open(infile)
                destImage = sourceImage
                # 縦長の画像の場合、回転させる
                if destImage.size[0] < destImage.size[1]:
                    destImage = destImage.rotate(270)
                destImage.thumbnail(max_size, Image.ANTIALIAS)
                destImage.save(os.path.join(outputDirPath,"s_" + os.path.basename(infile)))
                count += 1
                show_progress_bar(progress_bar_chr, progress_bar_width,total, count)
    
    if __name__=='__main__':
        #引数の数がおかしい場合
        if len(sys.argv) != 2: 
            print('Usage: # python %s [SourceImageDirectoryPath]' % sys.argv[0])
            quit()
    
        sourcePath = os.path.dirname(unicode(sys.argv[1],"mbcs") + '\\')
    
        if os.path.isdir(sourcePath) == False: 
            print('[%s]: Src directory does not exist.' % sourcePath)
            quit()
        elif os.path.isdir(TARGET_DIR) == False: 
            print('[%s]: Dest directory does not exist.' % TARGET_DIR)
            quit()
        elif sourcePath == TARGET_DIR: 
            print('The input destination is the same as the output destination. ')
            quit()
        else:
            shrinkImage(sourcePath)
    
    
    タグ:Python
    posted by MINE at 00:55 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit

    2009年11月29日

    [Python]CSVの列に出現する文字列をカウントするプログラム

    CSVから1列抽出して、単語の頻度をCSV出力するpythonコード。
    ネット見ながら一先ず書いてみた。

    あとは、コマンドラインから設定を指定できるようにすればいいだろう。日本語も通るか微妙。

    python2.6.4で動作確認。python3だと動かない。

    コード

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # CSV読んで、列(orファイル全体)に出現する単語をカウントする
    #
    import csv
    
    #設定
    read_column_index = 1
    input_csvfile = 'input.csv'
    output_csvfile = 'output.csv'
    
    #csv読み込み
    reader = csv.reader(open(input_csvfile,'r'))
    
    # Count
    dict = {}
    for row in reader:
       value = row[read_column_index]
       dict[value] = dict[value] + 1 if dict.get(value) else 1
    #CSV全体をカウントする場合有効にする
    # for value in row:
    # dict[value] = dict[value] + 1 if dict.get(value) else 1
    
    # CSV出力
    writer = csv.writer(file(output_csvfile, 'w'), lineterminator="\n")
    for k,v in dict.iteritems():
       writer.writerow([k,v]) 
    
    タグ:Python
    posted by MINE at 02:11 | Comment(0) | TrackBack(0) | Python | このブログの読者になる | 更新情報をチェックする | edit