2時間でPythonでKDE4の便利なプログラムを作成します

数時間の空き時間が職場に現れ、私は自分自身の生活を楽にすることに決めました。
職業(と私はプログラマーとして)によって、リモートサーバー上でやることがたくさんあり、ssh経由でのみアクセスできます。 また、プログラムをローカルで記述してデバッグし、それを動作中のマシンに置くのが最も便利です。 したがって、sshfsを使用すると便利です。 しかし、毎回mountコマンドを入力するのはうんざりです。タワーでスクリプトを書くのは面倒です。 そのため、sshfsマウントグラフィカルマネージャー、およびKDE4の他のすべてのものが必要でした。


代替案


当然、彼は自分で書いてから、最後まで抵抗しました。 Googleが答えをくれました。 しかし、適切なものは見つかりませんでした。
KDE3でのみ何らかの理由で獲得したksshfs
sshfsgui動作を望みませんでした。いくつかのJavaエラーが挙げられました。 yavamashinのいくつかの異なるバージョンと実装を試してみました-助けにはなりませんでした。

自分でやらなければなりません。

読む


まず、KDE4用のアプリケーションをどのように作成しますか? この知識は、 「Programming for KDE4」という記事から学びました。
残りはドキュメントによって助けられました。

フレーム


インターフェイスの観点から、私はsshfsguiに焦点を合わせました。 ここから始めます。
まず、アプリケーションのフレームワークを使用します。
PyKDE4 からkdeui import KApplicationKMainWindowKPushButtonKHBoxKVBoxKLineEditKListWidget
PyKDE4 からkdecore import i18nki18nKAboutDataKCmdLineArgs
PyQt4 から QtCoreを インポート
PyQt4 からQtGui import Qlabel
インポートシステム

クラス pyksshfsWindow KMainWindow

selected_name = False

def __init__ (self、parent = None) :#constructor
KMainWindow__init__ selfparent #親コンストラクターを呼び出す

appName = "pyksshfs"
カタログ = ""
programName = ki18n "PyKSshfs"
バージョン = "0.1"
description = ki18n sshfs を使用するためのGUIアプリケーション」
ライセンス = KAboutData License_GPL
copyright = ki18n "©Akademic"
テキスト = ki18n "none"
homePage = "プログラムサイト"
bugEmail = "エラーについて作成者と通信するためのメール"

aboutData = KAboutData appNamecatalogprogramNameversiondescriptionlicensecopyrighttexthomePagebugEmail
KCmdLineArgsinit sys。argvaboutData

app = KApplication
w = pyksshfsWindow
w 表示
アプリ exec_


私は一つのことを言います-それはすでに発売されており、この考えは私の心を温めます。 次のようになります。
Qt4ブランクアプリケーション

インターフェース


プログラムは2時間で、実際に単純なので、インターフェイスに関連するすべてのものを__init__メソッドに配置しました。 Qt Designerで苦しむのではなく、コードを書くだけです。

次のようになります。
def __init__ selfparent = None #constructor

KMainWindow__init__ selfparent #親コンストラクターを呼び出す

hbox = KHBox self #水平レイヤーを作成
hbox setMargin 10 #10ピクセルのインデント
自己setCentralWidget hbox #メインにする

#メイン水平内の2つの垂直レイヤー
vbox_left = KVBox hbox
vbox_right = KVBox hbox

#正しいレイヤーを上に揃える
hbox レイアウト setAlignment vbox_rightQtCore。Qt。AlignTop

#マウント用のデータ入力用フィールド
entry_name_label = QLabel 'Name:'vbox_right
自己entry_name = KLineEdit vbox_right
server_address_label = QLabel 'サーバーアドレス:'vbox_right
自己server_address = KLineEdit vbox_right

server_port_label = QLabel 'サーバーポート:'vbox_right
自己server_port = KLineEdit vbox_right

user_name_label = QLabel 'Username:'vbox_right
自己user_name = KLineEdit vbox_right

remote_path_label = QLabel 'リモートパス:'vbox_right
自己remote_path = KLineEdit vbox_right

local_path_label = QLabel 'Local path:'vbox_right
自己local_path = KLineEdit vbox_right

#ボタンのマウントとアンマウント
#別のレイヤーを作成
btn_hbox_right = KHBox vbox_right
connect_btn = KPushButton btn_hbox_right
connect_btnsetText i18n '接続'

disconnect_btn = KPushButton btn_hbox_right
disconnect_btnsetText i18n '切断'

#保存済みプロファイルのリスト
saved_list_label = QLabel 'Stored connections:'vbox_left
自己saved_list = KListWidget vbox_left
自己saved_listsetMaximumWidth 150

#プロファイルを保存および削除するためのボタン
btn_hbox_left = KHBox vbox_left
save_btn = KPushButton btn_hbox_left
save_btn setText i18n '保存'

delete_btn = KPushButton btn_hbox_left
delete_btnsetText i18n '削除'

したがって、この後、フォームを表示するプログラムがあります。
Qtフォーム、インターフェース

イベント処理


次に、プログラムの枠組みに命を吹き込む必要があります。
ユーザー(つまり、I)はボタンをクリックし、保存されたプロファイルのリストでプロファイルを選択することですべてのアクションを実行するため、これらの要素にイベントハンドラーをインストールする必要があります。 信号とスロットのメカニズムがこれに役立ちます。
簡単です:
#イベントハンドラーをボタンにバインド
#ここでsave_btnは保存ボタンオブジェクトを含む変数です
#QtCore.SIGNAL( 'clicked()')-「ボタンをクリック」というシグナル
#self.onSave-クリックを処理するために呼び出されるメソッド
自己connect save_btnQtCore。SIGNAL ' clicked ()' self。onSave
自己connect delete_btnQtCore。SIGNAL ' clicked ()' self。onDelete
自己connect connect_btnQtCore。SIGNAL 'clicked()' self。onConnect
自己connect disconnect_btnQtCore。SIGNAL ' clicked ()' self。onDisconnect

#最も困難なことは、「リスト内のアイテムをクリックした」シグナルの名前をドキュメントで見つけることでした
自己connect self。saved_listQtCore。SIGNAL 'itemClicked(QListWidgetItem *)' self。onSelectServer


プロファイルを保存しています

ハンドラー自体を作成するのはあなた次第です。 順番に始めましょう。プロファイルを保存し、プロファイルを削除します。
プロファイルをユーザーのホームディレクトリの〜/ .pyksshfs / hosts /に保存します。
プロファイルごとに1つのファイルファイル名は、フォームで「名前」と呼ばれるものです。
起動時に、プログラムがそのようなディレクトリがあるかどうかをチェックし、不在の場合に作成する必要があるのは論理的です。
これを行うには、プログラムの説明の後に次の洗練されていないコードを追加します。
config_path = osgetenv 'HOME' + '/.pyksshfs/hosts'
osで ない 場合パス isdir config_path
osmakedirs config_path0700


そして、インポートOSプログラムでファイルの先頭に
フォームフィールドの値をファイルに保存する最善の方法を考えて、私はおそらくPythonに設定を保存するための既製のモジュールがあると思いました。 そしてそれが起こった。
わずかなグーグルですぐに結果が得られました:import ConfigParser
onSaveメソッド:
def onSave self
'' '
設定を保存する
' ' '
自己の 場合entry_nametext #プロファイル名がある場合
config = ConfigParserRawConfigParser #構成を作成して入力する
config add_section '接続'
config 設定 「接続」「ホスト」自己サーバーアドレステキスト
config 設定 「接続」「ポート」自己サーバー ポートテキスト
config セット 'Connection''user_name'self。user_name。text
config set 'Connection''remote_path'self。remote_path。text
config set 'Connection''local_path'self。local_path。text

自己の 場合selected_name
osunlink self。config_path + '/' + self。selected_name

path = self config_path + '/' + self entry_nameテキスト
ファイル = オープン パス'w'
config write file #設定を保存
ファイル閉じる
自己selected_name = selfentry_nameテキスト
自己listServers #プロファイルのリストを更新


プロフィールリスト

メソッドの記述の最後に、新しいプロファイルがすぐにリストに表示されたらいいと思います。プログラムを開くと、保存されたプロファイルのリストも表示する必要があります。
そのため、出力を受信して​​一覧表示するメソッドをすぐに記述し、__ init__およびonSaveの最後に呼び出しを挿入します。
def listServers self
自己saved_listクリア
hosts = os listdir self。config_path
自己saved_listinsertItems Ohosts #この呼び出しで、ファイルのリストをリストウィジェットに追加します
自己の 場合selected_name #すでにプロファイルを選択している場合は、リストで選択する必要があります
item = self saved_listfindItems self。selected_nameQtCore。Qt。MatchExactly
自己saved_listsetItemSelected item [ O ]True

(何らかの理由で、Habrはコードに0を表示したくないため、大文字のOに置き換えました)。

アンマウント

さらに進みましょう。 リモートディレクトリをアンマウントする方法。 基本的に説明することはありません。

def onDisconnect self
if self。local_path。text
ossystem 'fusermount -u' + str self。local_path。text


取り付け

マウントははるかに興味深いです。 私はこの部分を最も長く苦しめました。 この方法のせいで、2時間以上かかったのは秘密です。 しかし、実際には、問題はそのような性質のものであったため、以前にそれらのことを知っていたなら、見出しに示された期限を完全に満たしていただろう。
問題:sshを使用してディレクトリをマウントするコマンドは対話型であり、ユーザーからのパスワードが必要です。 ただし、キーによる認証が行われた場合は必要ありません。 したがって、コマンドを作成し、実行し、パスワードが要求されているかどうかを確認してから、ユーザーに要求する必要があります。 パスワードが不要な場合は、ユーザーに触れないでください。
sshfsコマンドには、stdinでパスワードを渡すことができるパラメーターがあります。 ただし、ユーザーは、パスワードが不要な場合、あまり良くないものを事前に尋ねる必要があります。
別の微妙な点があります。 sshを介してサーバーにアクセスしたことがない場合は、「彼を信頼しますか?」と尋ねられます。

一般に、これらのケースを何らかの形で処理する必要があります。 このような問題を解決するために、pexpectモジュール(pexpectのインポート)があります。 これを使用すると、対話型プログラム(telnet、ftp、sshなど)で作業できます。 さて、コードを表示する時間です。
def onConnect self
コマンド = 'sshfs'
自己の 場合user_name テキスト
command + = self user_name テキスト + '@'
command + = self server_addressテキスト
自己の 場合remote_pathテキスト
command + = ':' + self remote_pathテキスト
その他
コマンド + = ':/'

自己の 場合server_portテキスト
command + = '-p' + selfserver_portテキスト

command + = '' + selflocal_pathテキスト

sshfs = pexpect spawn str command env = { 'SSH_ASKPASS' '/ dev / null' }
ssh_newkey = '接続を続行してもよろしいですか?
i = sshfs expect [ ssh_newkey'assword:'pexpect。EOFpexpect。TIMEOUT ]

i = = 0の 場合
sshfs sendline 'yes'
i = sshfs expect [ ssh_newkey'assword:'pexpect。EOF ]
i = = 1の 場合
#パスワードが要求されない場合
askpasscmd = 'ksshaskpass%s' self entry_nameテキスト
パスワード = pexpect 実行 askpasscmd split '\ n' [ 1 ]
sshfs sendline パスワード
j = sshfs expect [ pexpect。EOF'assword:' ]
j = = 1の 場合
#パスワードが正しくありません、強制的に接続を閉じます
「パスワードが正しくありません」を 印刷
sshfs 閉じる True
#p.terminate(True)
elif i = = 2
#すべての問題
print "エラーが見つかりました:%s" sshfs前に
elif i = = 3
#タイムアウト
print "Timeout:%s" sshfs前に
sshfsを出力します。 前に

linux-volume-manager-fuse-kde4プロジェクトからコードの一部を取りました。 最初は私のコードは動作したくありませんでしたが、コードが動作した後、私はこれをすべて同じままにすることにしました。 より多くのオプションを処理します。
ユーザーからパスワードを取得するには、ksshaskpassプログラムを使用しました。 第一に、書かないために、第二に、彼女はkwalletdからパスワードを保存/受信する方法を知っています。これは非常に便利です。
オリジナルのコードは、ksshaskpassのドキュメントによるとパスワードを返す必要があるため、まったく機能しませんでしたが、その代わりに、パスワードに加えて、他のデバッグ行を返します。 彼女はこのように除外しなければなりませんでした
パスワード= pexpect.run( 'ksshaskpass').split( '\ n')[1]
ところで、突然デバッグ行が消えると、プログラムは動作を停止します。

プロフィールのアップロード

ほとんどすべての準備が整いました。 最後のアクションは残ります。ユーザーがリストから選択したときにプロファイルをロードします。 すぐにコード。
def onSelectServer selfitem
「」
seved_listでアイテムが選択されている場合、ファイルから設定を取得

name = item テキスト #ファイル名
自己selected_name = name #選択を覚えておいてください

config = ConfigParserRawConfigParser
config readfp open self。config_path + '/' + name #設定を開きます

#設定からフォームフィールドに入力
自己entry_namesetText name
自己server_addresssetText config。get 'Connection''host'
自己server_portsetText config。get 'Connection''port'
自己user_name setText config。get 'Connection''user_name'
自己remote_pathsetText config。get 'Connection''remote_path'
自己local_pathsetText config。get 'Connection''local_path'


結果


以上です。 ほんの2、3時間で、Pythonシンタックス、グーグル、ブラックベルトのみを使用して、かなり実用的なコピー/貼り付けプログラムを作成しました。
おそらく記事では、コードの一部を見逃していました。
ですから、完全に動作するpyKSshfsバージョンダウンロードするのが最善です。

最後にスクリーンショット:
終了したプログラム

計画


プログラムの作成の途中で、プラズマアプレットとしてより便利になると思いました。 そして、フラッシュドライブをマウントするためのアプレットのように見えるはずです。 しかし、ksshaskpassで忙しかったので、延期することにしました。 たぶんすぐにやろう。 または多分あなたの一人が私の先を行くでしょう-私はただうれしいです。

参照資料


  1. pyKSshfsをダウンロードします
  2. 「KDE4のプログラミング」
  3. PyQtドキュメント
  4. Kommanderスクリプトksshfs
  5. sshfsgui javaプログラム
  6. コードの一部はここで取得されました。


ご清聴ありがとうございました!


これをすべて読むことができたすべての人のおかげで、私はそれが簡単ではなかったことを知っています。 =)
皆さんに幸運を!

Source: https://habr.com/ru/post/J52217/


All Articles