python での try-except-else-finally

下のサンプルコードと実行結果を参照.

  • tryブロックで例外が発生して,except で捕捉されなかった場合には,elseは実行されない (arg = 2).
  • try や except や else で return されても,finally は実行される (arg = 0,3,4).
  • try で return されると,elseは実行されない (arg = 3).

サンプルコード:

class A(Exception):
    pass
class B(Exception):
    pass

def func(arg):
    print('------ {}'.format(arg))
    try:
        if (arg <= 1):
            raise A()
        elif (arg == 2):
            raise B()
        elif (arg == 3):
            return
    except A:
        print("A")
        if (arg == 0):
            return
    else:
        print("else")
        if (arg == 4):
            return
    finally:
        print("finally")
    print("after try")

for arg in range(6):
    try:
        func(arg)
    except:
        print("B (uncaught)")

実行結果:

------ 0
A
finally
------ 1
A
finally
after try
------ 2
finally
B (uncaught)
------ 3
finally
------ 4
else
finally
------ 5
else
finally
after try

 

Virtualbox + Ubuntu (hostはWindows)

Windows host の VirtualBox で,Ubuntu (16.04LTS) を入れようとしている.

日本語キーボードで US JP を使って英語配列のエミュレートという環境 (いろいろ事情が…)  Ubuntuのインストールの時には,US JP のエミュレートを無向にしておいて,日本語キーボードだというふうに設定するべきであるようだ.その後,英語配列エミュレートを有効にすれば,Virtual Box のなかでもエミュレートしてくれる.

ホームディレクトリの日本語ディレクトリ名を英語に変える:

$LANG=C xdg-user-dirs-gtk-update

(https://qiita.com/taiko19xx/items/d1a001bfc25245b91354 を参照.)

moodle 課題のダウンロード (更新)

前記事のバージョンアップ.moodle 3.4 で,課題一括ファイルダウンロードの際にユーザ名 (username) を入れるための修正.変なコードも入っているけど余り気にしないで….

--- mod/assign/locallib.php-orig        2018-02-22 19:14:37.752749187 +0900
+++ mod/assign/locallib.php     2018-02-22 19:40:12.383882868 +0900
@@ -3388,7 +3388,8 @@
                     $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
                 } else {
                     $prefix = str_replace('_', ' ', $groupname . fullname($student));
-                    $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
+                    $prefix = $student->username . '_' . $prefix;
+                    // $prefix = clean_filename($prefix . '_' . $this->get_uniqueid_for_user($userid));
                 }

                 if ($submission) {
@@ -3402,6 +3403,7 @@
                                 $pluginfiles = $plugin->get_files($submission, $student);
                                 foreach ($pluginfiles as $zipfilepath => $file) {
                                     $subtype = $plugin->get_subtype();
+                                    if (strcmp($subtype, "assignsubmission") == 0) { $subtype = "as"; }
                                     $type = $plugin->get_type();
                                     $zipfilename = basename($zipfilepath);
                                     $prefixedfilename = clean_filename($prefix .
@@ -3427,6 +3429,7 @@
                                 $pluginfiles = $plugin->get_files($submission, $student);
                                 foreach ($pluginfiles as $zipfilename => $file) {
                                     $subtype = $plugin->get_subtype();
+                                    if (strcmp($subtype, "assignsubmission") == 0) { $subtype = "as"; }
                                     $type = $plugin->get_type();
                                     $prefixedfilename = clean_filename($prefix .
                                                                        '_' .

画像のデータに不足があります

latex で作成したPDFファイルを,Adobe Acrobat (11 および DC) で読んでいったら,画像を取り込んでいるところで,「画像のデータに不足があります」というダイアログボックスが出て,画像が表示されなかった.

# 今までこんなこと無かったと思うのだけれどなあ.気がついていなかっただけかなあ.

その画像は,JPGファイルを Cygwin の ImageMagick の convert コマンドで PDF に変換したもので,それを includegraphics で読み込んでいる.プレビューはsumatra PDF で行っており,何の問題もなかった.検索をしてみると,Adobe は,過去にこの問題を認識している (Acrobat 9 とか 10 とかの時代) が,すでに修正済み,とのことらしい.

よくよくプロセスを見てみたら,dvipdfmx が警告を出していた:

dvipdfmx:warning: Version of PDF file (1.7) is newer than version limit specification.
dvipdfmx:warning: pdf_open: Not a PDF 1.[1-5] file.
dvipdfmx:warning: Trying to include PDF file which has newer version number than output PDF: 1.5.

ということで,画像のPDFファイルフォーマットが良くなかったということらしい.たまたまGraphicsMagick が cygwin にインストールされていたので,この convert コマンドをつかってみた.これで良いらしい.

$ gm convert -density 300 fig01.jpg fig01.pdf
$ pdfinfo fig01.pdf | grep 'PDF version'
PDF version: 1.2

実際に動作した.また,Acrobat にJPGファイルを読み込ませて保存した場合も,(今度はdvipdfmxの警告が 1.6 であって危ない,に変わったが) 動作した.(コマンドラインじゃないので勘弁して欲しいが.)  なお,dvipdfmx が警告を出すのは,自分が作るPDFファイルが1.5仕様だからであって,オプションで1.7仕様のものを作るようにする (-V 7) と,警告は出てこない.しかし,このようにして作成したPDFも,Acrobat で読むと「画像のデータに不足があります」になる.

keywords: tex image pdf version

ファイルの読み込み: [Char] と ByteString (つづき)

前回に引き続いて,今度は文字列の操作.一行72文字のファイルを読み込ませ,aの文字数を数える,というのと,aが4回以上現れる行数を数える,というのを書いてみた.ByteString の場合には,B.fold* を使うことになるようだ.今回は,ByteString.Char8 と ByteString.Lazy.Char8 も比較した.

結果. 文字数を数える:

10万行 100万行 200万行 500万行
[Char] 0.19 0.39 2.7 6.7
ByteString.Char8 0.08 0.08 0.46 1.12
ByteString.Lazy.Char8 0.07 0.08 0.29 0.63

 

結果. 行数を数える:

10万行 100万行 200万行 500万行
[Char] 1.38 3.38 6.7 17
ByteString.Char8 0.27 0.33 0.60 1.38
ByteString.Lazy.Char8 0.20 0.28 0.50 1.15

測定対象プログラム

import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as BL
import Data.List
import System.Environment

type TpFold s a = ((a -> Char -> a) -> a -> s -> a)

opFunc :: Int -> Char -> Int
opFunc acc c = if c == 'a' then acc + 1 else acc

testFn1 :: TpFold s Int -> s -> Int
testFn1 fold = fold opFunc 0

testFn2 :: TpFold s Int -> [s] -> Int
testFn2 fold = sum . map (\s -> if fold opFunc 0 s >= 4 then 1 else 0)

main :: IO ()
main = do
  [arg] <- getArgs
  case read arg of 
    1 -> print . testFn1 foldl'    =<< getContents 
    2 -> print . testFn1 B.foldl'  =<< B.getContents 
    3 -> print . testFn1 BL.foldl  =<< BL.getContents 
    4 -> print . testFn2 foldl'    . lines    =<< getContents 
    5 -> print . testFn2 B.foldl'  . B.lines  =<< B.getContents 
    6 -> print . testFn2 BL.foldl' . BL.lines =<< BL.getContents 
    _ -> error "unknown option"

keyword: haskell performance

Verbatim環境での中括弧,\symbol

fancyvrb package の Verbatim 環境での話.
例えばイタリックにしたいとき,次のように書けば良い.

\begin{Verbatim}[commandchars=\\\{\}]
Roman \textit{Italic} Roman
\end{Verbatim}

Verbatim のボディの中に中括弧がある場合には,次で良いはずなのだが,実際には機能しない.(切り替わらない)

\begin{Verbatim}[commandchars=\\\<\>]
Roman \textit<Italic> Roman { in braces }
\end{Verbatim}

一行バージョンはうまく動くのだが…

\Verb[commandchars=\\\<\>]|Roman \textit<Italic> Roman { in braces }|

対応策.\symbol を使う.中括弧の閉じと開きは\symbol{123} と \symbol{125} なので,次のようになる.

\begin{Verbatim}[commandchars=\\\{\}]
Roman \textit{Italic} Roman \symbol{123} in braces \symbol{125}

\symbol は,\texttt でアンダースコアがうまくでない話にも使えて,\texttt{abc\symbol{95}def := 0;} 等と書ける.

keywords: tex latex brace