Python + pywinauto တွင် desktop GUI ကို အလိုအလျောက်လုပ်ခြင်း- MS UI Automation ဖြင့် မိတ်ဆွေဖွဲ့နည်း

Python စာကြည့်တိုက် pywinauto — သည် desktop GUI application များကို အလိုအလျောက်လုပ်ဆောင်ရန်အတွက် open source project တစ်ခုဖြစ်သည်။ Windowsပြီးခဲ့သည့် နှစ်နှစ်အတွင်း၊ ၎င်းသည် အဓိက အင်္ဂါရပ်အသစ်များကို ထည့်သွင်းခဲ့သည်-

  • MS UI Automation နည်းပညာအတွက် ပံ့ပိုးမှု။ interface သည် အတူတူပင်ဖြစ်ပြီး ယခုအခါ WinForms၊ WPF၊ Qt5 တို့ကို ပံ့ပိုးပေးပါသည်။ Windows Store (UWP) စသည်ဖြင့် - ဖွင့်ထားသော အရာအားလုံးနီးပါး Windows.
  • နောက်ခံများ/ပလပ်အင်များ၏ စနစ် (လက်ရှိတွင် ၎င်းတို့ထဲမှ နှစ်ခုရှိသည်- ပုံသေ "win32" နှင့်အသစ် "uia") ထို့နောက် ကျွန်ုပ်တို့သည် cross-platform သို့ ချောမွေ့စွာ ရွေ့လျားသည်။
  • မောက်စ်နှင့် ကီးဘုတ်အတွက် Win32 ချိတ်များ (pyHook ၏ စိတ်ဓာတ်ရှိ hot keys)။

ဒက်စ်တော့ အလိုအလျောက်စနစ်အတွက် (အလေးအနက် နှိုင်းယှဉ်ဟန်ဆောင်ခြင်းမပြုဘဲ) ပွင့်လင်းရင်းမြစ်တွင် ရနိုင်သည့်အရာများအကြောင်း အတိုချုပ်ကိုလည်း ပေးပါမည်။

ဤဆောင်းပါးသည် Minsk ရှိ SQA Days 20 ညီလာခံမှ အစီရင်ခံစာ၏ တစ်စိတ်တစ်ပိုင်း မှတ်တမ်းတစ်ခုဖြစ်သည်။ဗီဒီယိုတိပ်ခွေ и ဆလိုက်များ) တစ်စိတ်တစ်ပိုင်း ရုရှားဗားရှင်း လမ်းညွှန်စတင် pywinauto အတွက်။

ဤဧရိယာရှိ open source ၏ အကျဉ်းချုပ်ဖြင့် စတင်ကြပါစို့။ ဒက်စ်တော့ GUI အပလီကေးရှင်းများအတွက်၊ Selenium ပါရှိသည့် ဝဘ်ထက် အရာအားလုံးသည် ပိုမိုရှုပ်ထွေးပါသည်။ ဤသည်မှာ အဓိက ချဉ်းကပ်နည်းများဖြစ်သည်။

ညှိနှိုင်းနည်းလမ်း

ကလစ်အမှတ်များကို Hardcode၊ ကျွန်ုပ်တို့သည် အောင်မြင်သော hits များကို မျှော်လင့်ပါသည်။
[+] Cross-platform၊ အကောင်အထည်ဖော်ရန်လွယ်ကူသည်။
[+] စမ်းသပ်မှုမှတ်တမ်းများကို "record-replay" လုပ်ရန် လွယ်ကူသည်။
[-] ပြောင်းလဲနေသော မျက်နှာပြင် ရုပ်ထွက်၊ အပြင်အဆင်၊ ဖောင့်များ၊ ဝင်းဒိုးအရွယ်အစား စသည်ဖြင့် ပြောင်းလဲခြင်းအတွက် အတည်ငြိမ်ဆုံး။
[-] ကြီးမားသော ပံ့ပိုးကူညီမှု ကြိုးပမ်းမှုများ လိုအပ်သည်၊ ၎င်းသည် စမ်းသပ်မှုများကို အစမှ ပြန်ထုတ်ရန် သို့မဟုတ် ကိုယ်တိုင်စမ်းသပ်ရန် မကြာခဏ ပိုမိုလွယ်ကူသည်။
[-] လုပ်ဆောင်ချက်များကိုသာ အလိုအလျောက်လုပ်သည်၊ ဒေတာကို အတည်ပြုခြင်းနှင့် ပြန်လည်ရယူခြင်းအတွက် အခြားနည်းလမ်းများရှိပါသည်။

ကိရိယာများ (ပလပ်ဖောင်းဖြတ်ကျော်): autopy, PyAutoGUI, PyUserInput နှင့်အခြားများစွာ။ ပုံမှန်အားဖြင့်၊ ပိုမိုရှုပ်ထွေးသော ကိရိယာများတွင် ဤလုပ်ဆောင်ချက်ပါဝင်သည် (အမြဲတမ်း ဖြတ်ကျော်ခြင်းမဟုတ်)။

Coordinate method သည် အခြားသော ချဉ်းကပ်မှုများကို ဖြည့်စွက်ပေးနိုင်သည်ဟု ဆိုရကျိုးနပ်ပါသည်။ ဥပမာအားဖြင့်၊ စိတ်ကြိုက်ဂရပ်ဖစ်အတွက်၊ သင်သည် နှိုင်းရသြဒီနိတ်များ (ဝင်းဒိုး/ဒြပ်စင်၏ ဘယ်ဘက်အပေါ်ထောင့်မှ၊ စခရင်တစ်ခုလုံးမဟုတ်ဘဲ) ကိုနှိပ်နိုင်သည် - ၎င်းသည် အများအားဖြင့် အလွန်ယုံကြည်စိတ်ချရသည်၊ အထူးသဖြင့် သင်သည် အဆိုပါအလျား/အနံကို ထည့်သွင်းစဉ်းစားပါက၊ ဒြပ်စင်တစ်ခုလုံး (ထို့နောက် မတူညီသော မျက်နှာပြင် ရုပ်ထွက်များသည် ထိခိုက်မည်မဟုတ်ပါ)။

အခြားရွေးချယ်စရာ- စမ်းသပ်မှုအတွက် တည်ငြိမ်သောဆက်တင်များပါရှိသည့် စက်တစ်လုံးတည်းကိုသာ ခွဲဝေချထားပါ (ပလပ်ဖောင်းမဟုတ်သော်လည်း အချို့ကိစ္စများတွင် ၎င်းသည် ကောင်းမွန်သည်)။

အကိုးအကား ရုပ်ပုံအသိအမှတ်ပြုမှု

[+] ပလပ်ဖောင်း ဖြတ်ပိုင်း
[+-] အတော်အတန်ယုံကြည်စိတ်ချရသော (သြဒိနိတ်နည်းလမ်းထက် ပိုကောင်းသည်)၊ သို့သော် လှည့်ကွက်အချို့ လိုအပ်နေသေးသည်။
[-+] နှေးသောကြောင့်၊ အသိအမှတ်ပြုခြင်းဆိုင်ရာ အယ်လဂိုရီသမ်များအတွက် CPU အရင်းအမြစ်များ လိုအပ်သည်။
[-] စည်းမျဉ်းအရ စာသားအသိအမှတ်ပြုခြင်း (OCR) သည် မေးခွန်းမထုတ်ဘဲ => စာသားဒေတာကို မရနိုင်ပါ။ ကျွန်ုပ်သိသလောက်၊ ရှိပြီးသား OCR ဖြေရှင်းချက်များသည် ဤလုပ်ငန်းအမျိုးအစားအတွက် အလွန်ယုံကြည်စိတ်ချရခြင်းမရှိသည့်အပြင် တွင်တွင်ကျယ်ကျယ် အသုံးမပြုပါ (ယင်းကိစ္စမဟုတ်ပါက မှတ်ချက်များတွင် ကြိုဆိုပါသည်)။

တူရိယာ: Sikuli, လက်ပါးစေ (Sikuli-compatible, pure Python)၊ PyAutoGUI.

သုံးစွဲနိုင်မှုနည်းပညာ

[+] အယုံကြည်ရဆုံးနည်းလမ်းမို့ပါ။ စနစ် သို့မဟုတ် မူဘောင်ဖြင့် မည်သို့ပြန်ဆိုသည်ဖြစ်စေ စာသားဖြင့် ရှာဖွေနိုင်စေပါသည်။
[+] စာသားဒေတာ => စမ်းသပ်မှုရလဒ်များကို အတည်ပြုရန် ပိုမိုလွယ်ကူစေပါသည်။
[+] စည်းကမ်းအတိုင်း အလျင်မြန်ဆုံးမို့ပါ။ CPU အရင်းအမြစ်များကို လုံးဝနီးပါး စားသုံးပါသည်။
[-] cross-platform tool တစ်ခုပြုလုပ်ရန် ခက်ခဲပါသည်- open-source libraries အားလုံးသည် accessibility နည်းပညာ တစ်ခု သို့မဟုတ် နှစ်ခုကို ပံ့ပိုးပေးပါသည်။ Windows/Linux/TestComplete၊ UFT သို့မဟုတ် Squish ကဲ့သို့သော အခကြေးငွေပေးရသည့် ဆော့ဖ်ဝဲများမှလွဲ၍ MacOS ကို မည်သူမျှ အပြည့်အဝ ပံ့ပိုးမထားပါ။
[-] ထိုသို့သောနည်းပညာသည် မူအရ အမြဲတမ်းမရနိုင်ပါ။ ဥပမာအားဖြင့်၊ VirtualBox အတွင်းရှိ loading screen ကို စမ်းသပ်ခြင်း - ရုပ်ပုံအသိအမှတ်ပြုခြင်းမရှိဘဲ ၎င်းကို လုပ်ဆောင်၍မရပါ။ သို့သော် ဂန္ထဝင်မြောက်များစွာသောကိစ္စများတွင်၊ အများသုံးစွဲနိုင်မှုချဉ်းကပ်မှုမှာ အသုံးပြုနိုင်သေးသည်။ ဒါကို ဆက်လက်ဆွေးနွေးသွားမှာဖြစ်ပါတယ်။

တူရိယာ: TestStack.White C# တွင်၊ Winium.Desktop C# တွင် (Selenium compatible)၊ MS WinApp Driver C# တွင် (Appium compatible)၊ pywinauto, pyatom (LDTP တွဲဖက်အသုံးပြုနိုင်သည်) Python-UIAutomation-for-Windows, အလိုအလျောက်လုပ်ဆောင်ခြင်း။ ပတ္တမြား၊ LDTP (Linux Desktop Testing Project) နှင့် ၎င်း၏ Windows ဗားရှင်း Cobra.

LDTP သည် သုံးစွဲနိုင်မှုနည်းပညာများကို အခြေခံ၍ တစ်ခုတည်းသော cross-platform open-source tool (အတိအကျအားဖြင့်၊ စာကြည့်တိုက်များ၏ မိသားစု) ဖြစ်ကောင်းဖြစ်နိုင်သည်။ ဒါပေမယ့် သိပ်နာမည်ကြီးတာတော့ မဟုတ်ပါဘူး။ ငါကိုယ်တိုင်မသုံးဖူးပေမယ့် ပြန်လည်သုံးသပ်ချက်တွေအရတော့ သူ့ရဲ့ interface က အဆင်ပြေဆုံးမဟုတ်ပါဘူး။ သင့်တွင် အပြုသဘောဆောင်သော အကြံပြုချက်ရှိပါက ၎င်းကို မှတ်ချက်များတွင် မျှဝေပါ။

Backdoor စမ်းသပ်ခြင်း (သို့မဟုတ် မိုးလုံလေလုံစက်ဘီး)

Cross-platform အပလီကေးရှင်းများအတွက်၊ developer များကိုယ်တိုင် စမ်းသပ်နိုင်မှုသေချာစေရန် အတွင်းပိုင်းယန္တရားတစ်ခုကို ဖန်တီးလေ့ရှိသည်။ ဥပမာအားဖြင့်၊ ၎င်းတို့သည် အပလီကေးရှင်းတွင် ဝန်ဆောင်မှု TCP ဆာဗာတစ်ခုကို ဖန်တီးပြီး၊ စမ်းသပ်မှုများနှင့် ချိတ်ဆက်ကာ စာသားအမိန့်များပေးပို့ခြင်း- ဘာကိုနှိပ်ရမည်၊ ဒေတာရယူရန် နေရာစသည်ဖြင့်၊ ယုံကြည်နိုင်သော်လည်း universal မဟုတ်ပါ။

အခြေခံ ဒက်စ်တော့ အသုံးပြုနိုင်မှု နည်းပညာများ

ကောင်းသော Win32 API အဟောင်း

အများစုမှာ Windows WPF မထွက်ခင်နှင့် ထွက်ပြီးနောက်တွင် ရေးသားခဲ့သော application များ Windows Store များကို Win32 API တွင် တစ်နည်းနည်းဖြင့် တည်ဆောက်ထားသည်။ ဆိုလိုသည်မှာ MFC၊ WTL၊ C++ Builder၊ Delphi၊ VB6—ဤကိရိယာများအားလုံးသည် Win32 API ကိုအသုံးပြုသည်။ Windows Form များသည် အများအားဖြင့် Win32 API နှင့် တွဲဖက်အသုံးပြုနိုင်ပါသည်။

တူရိယာ: ခေါင်မိုးမှာ (VB နှင့်ဆင်တူသည်) နှင့် Python wrapper pyautoit, AutoHotkey ပါ (ကိုယ်ပိုင်ဘာသာစကား၊ IDispatch COM interface တစ်ခုပါရှိသည်) pywinauto (စပါးအုံး) အလိုအလျောက်လုပ်ဆောင်ခြင်း။ (ပတ္တမြား) win32-autogui (ပတ္တမြား)။

Microsoft UI အလိုအလျောက်စနစ်

အဓိကအားသာချက်- MS UI Automation နည်းပညာသည် GUI အပလီကေးရှင်းအများစုကို ပံ့ပိုးပေးသည်။ Windows ရှားရှားပါးပါး ခြွင်းချက်တွေတော့ ရှိပါတယ်။ ပြဿနာက Win32 API ထက် သင်ယူရတာ သိပ်မလွယ်ပါဘူး။ မဟုတ်ရင် ဘယ်သူမှ ဒီအတွက် wrapper တွေ ဖန်တီးမှာ မဟုတ်ပါဘူး။

တကယ်တော့၊ ဒါက စိတ်ကြိုက် COM အင်တာဖေ့စ်အစုတစ်ခု (အဓိကအားဖြင့် UIAutomationCore.dll) နှင့် ဖောင်တွင် .NET wrapper ပါရှိပါသည်။ namespace System.Windows.Automation. စကားမစပ်၊ အချို့သော UI ဒြပ်စင်များ လွဲချော်သွားနိုင်သောကြောင့် ၎င်းတွင် မိတ်ဆက်ထားသော ချို့ယွင်းချက်တစ်ခုရှိသည်။ ထို့ကြောင့် UIAutomationCore.dll ကို တိုက်ရိုက်အသုံးပြုခြင်းသည် ပိုကောင်းသည် (C# တွင် UiaComWrapper အကြောင်း ကြားသိရပါက၊ ၎င်းသည် ၎င်းဖြစ်သည်)။

COM အင်တာဖေ့စ် အမျိုးအစားများ

(၁) အခြေခံ IU လူသိများသည် - "မကောင်းမှုအားလုံး၏အမြစ်" ။ အနိမ့်ဆုံးအဆင့်၊ မည်သည့်အခါမျှ အသုံးပြုရလွယ်ကူသည်။
(၂) IDispatch နှင့် ဆင်းသက်လာမှုများ (ဥပမာ Excel.Applicationwin32com.client ပက်ကေ့ဂျ် (pyWin32 နှင့် ပါ၀င်သည်) ကို အသုံးပြု၍ Python တွင်အသုံးပြုနိုင်ပါသည်။ အဆင်ပြေဆုံးနှင့်အလှဆုံးရွေးချယ်မှု။
(၃) Third-party Python ပက်ကေ့ခ်ျဖြင့် အလုပ်လုပ်နိုင်သော စိတ်ကြိုက်အင်တာဖေ့စ်များ အမျိုးအစားများ.

တူရိယာ: TestStack.White C# တွင်၊ pywinauto ၅+ Winium.Desktop C# တွင်၊ Python-UIAutomation-for-Windows (UIAutomationCore.dll ပေါ်ရှိ C wrappers အတွက် ၎င်းတို့၏ အရင်းအမြစ်ကုဒ်ကို မဖော်ပြပါ)၊ အလိုအလျောက်လုပ်ဆောင်ခြင်း။ Ruby ၌။

AT-SPI

မိသားစုရဲ့ ပုဆိန်အားလုံးနီးပါး ရှိနေပေမယ့်လည်း Linux X Window System (Fedora 25 မှာ "X" ကို Wayland နဲ့ အစားထိုးခဲ့ပါတယ်) ပေါ်မှာ တည်ဆောက်ထားတဲ့ "X" ဟာ top-level windows တွေနဲ့ mouse/keyboard တွေကိုပဲ လည်ပတ်ခွင့်ပြုပါတယ်။ button တွေ၊ list box တွေ စတာတွေကို အသေးစိတ် analysis လုပ်ဖို့အတွက် AT-SPI နည်းပညာရှိပါတယ်။ အသုံးအများဆုံး window manager တွေမှာ AT-SPI registry daemon လို့ခေါ်တဲ့ software တစ်ခုရှိပြီး application တွေအတွက် automated GUI တစ်ခု (အနည်းဆုံး Qt နဲ့ GTK တွေကို support လုပ်ပါတယ်) ကို ပံ့ပိုးပေးပါတယ်)။

တူရိယာ: pyatspi2.

ကျွန်တော့်အမြင်အရ pyatspi2 တွင် PyGObject ကဲ့သို့သော မှီခိုမှုများစွာပါရှိသည်။ နည်းပညာကိုယ်တိုင်က ပုံမှန်ပြောင်းလဲနေသော စာကြည့်တိုက်တစ်ခုအဖြစ် ရရှိနိုင်သည်။ libatspi.so. တစ်ခုရှိပါတယ်။ ကိုးကားစရာလက်စွဲစာအုပ်pywinauto library အတွက်၊ ကျွန်ုပ်တို့သည် AT-SPI ပံ့ပိုးမှုကို ဤနည်းဖြင့် အကောင်အထည်ဖော်ရန် စီစဉ်ထားသည်- libatspi.so နှင့် ctypes module ကို တင်ခြင်းဖြင့်ဖြစ်သည်။ တစ်ခုတည်းသော အသေးအဖွဲပြဿနာမှာ GTK+ နှင့် Qt application များအတွက် အနည်းငယ်ကွဲပြားသောကြောင့် မှန်ကန်သော version ကို အသုံးပြုခြင်းပင်ဖြစ်သည်။ pywinauto 0.7.0 ၏ ဖြစ်နိုင်ခြေရှိသော ထွက်ရှိမှုတွင် အပြည့်အဝ ပံ့ပိုးမှု ပါဝင်မည်ဖြစ်သည်။ Linux ၂၀၁၈ ခုနှစ် ပထမနှစ်ဝက်တွင် ပြီးစီးမည်ဟု မျှော်လင့်ရသည်။

Apple Accessibility API

MacOS တွင် ၎င်း၏ကိုယ်ပိုင် အလိုအလျောက်စနစ်သုံးဘာသာစကား AppleScript ရှိသည်။ Python တွင်ဤကဲ့သို့သောအရာတစ်ခုခုကိုအကောင်အထည်ဖော်ရန်၊ သင် ObjectiveC မှလုပ်ဆောင်ချက်များကိုအသုံးပြုရန်လိုအပ်သည်။ အစတွင်၊ MacOS 10.6 ဖြင့် pyobjc ပက်ကေ့ဂျ်ကို ကြိုတင်ထည့်သွင်းထားသည့် Python တွင် ထည့်သွင်းထားသည်။ ၎င်းသည် pywinauto တွင် အနာဂတ်ပံ့ပိုးမှုများအတွက် မှီခိုမှုစာရင်းပြုစုရန်လည်း ပိုမိုလွယ်ကူစေမည်ဖြစ်သည်။

ကိရိယာများ- Apple Script ဘာသာစကားအပြင်၊ ၎င်းကို အာရုံစိုက်သင့်သည်။ ATOMac, aka pyatom ။ ၎င်းသည် LDTP နှင့်သဟဇာတရှိသောအင်တာဖေ့စ်ဖြစ်သည်၊ သို့သော်သီးသန့်စာကြည့်တိုက်တစ်ခုလည်းဖြစ်သည်။ အဲဒါရှိတယ်။ macO တွင် iTunes အလိုအလျောက်လုပ်ဆောင်ခြင်း၏ဥပမာငါ့ကျောင်းသားကရေးတယ်။ လူသိများသောပြဿနာတစ်ခုရှိသည်- ပြောင်းလွယ်ပြင်လွယ်အချိန်များအလုပ်မလုပ်ပါ (နည်းလမ်းများ waitFor*) ဒါပေမယ့် ခြုံငုံကြည့်ရင်တော့ မကောင်းပါဘူး။

pywinauto နဲ့ စတင်နည်း

ပထမအဆင့်သည် GUI အရာဝတ္တုစစ်ဆေးရေးအရာရှိ (Spy tool ဟုခေါ်သည်) ဖြင့် သင့်ကိုယ်သင် လက်နက်တပ်ဆင်ရန်ဖြစ်သည်။ ၎င်းသည် သင့်အား အပလီကေးရှင်းအတွင်းမှ လေ့လာရန် ကူညီပေးလိမ့်မည်- ဒြပ်စင်များ၏ အထက်အောက်ဖွဲ့စည်းပုံ၊ မည်သို့သော ဂုဏ်သတ္တိများ ရှိနိုင်မည်နည်း။ အကျော်ကြားဆုံးဆိုဒ်စစ်ဆေးရေးမှူးများ-

  • သူလျှို++ - Express သို့မဟုတ် Community Edition အပါအဝင် Visual Studio နှင့် ပါဝင်သည်။ Win32 API ကိုအသုံးပြုသည်။ သူ့ကိုယ်ပွားလို့လည်း သိကြပါတယ်။ AutoIt Window အချက်အလက်.
  • Inspect.exe ကိုစစ်ဆေးပါ။ — တွင် ပါဝင်သည် Windows SDK။ သင်ထည့်သွင်းပြီးပါက ၎င်းသည် 64-bit တွင်ရှိနေပါသည်။ Windows ဖိုဒါထဲမှာ ရှာလို့ရပါတယ် C:Program Files (x86)Windows Kits<winver>binx64. စစ်ဆေးရေးမှူးကိုယ်တိုင်၌ သင်သည် မုဒ်တစ်ခုကို ရွေးချယ်ရန် လိုအပ်သည်။ UI အလိုအလျောက်စနစ် MS AA အစား (Active Accessibility၊ UI Automation ၏ ဘိုးဘေး)။

အပလီကေးရှင်းကို ဖြတ်၍ စစ်ဆေးပြီးနောက်၊ ကျွန်ုပ်တို့ အသုံးပြုမည့် နောက်ခံကို ရွေးချယ်ပါ။ Application object ကိုဖန်တီးသောအခါ backend ၏အမည်ကိုသတ်မှတ်ရန်လုံလောက်သည်။

  • backend=”win32″ — မူရင်းအတိုင်းအသုံးပြုနေစဉ်၊ MFC၊ WTL၊ VB6 နှင့် အခြားသော အမွေအနှစ်အပလီကေးရှင်းများနှင့် ကောင်းစွာအလုပ်လုပ်သည်။
  • backend=”uia” — MS UI Automation အတွက် backend အသစ်- WPF နှင့် WinForms တို့နှင့် ပြီးပြည့်စုံစွာ အလုပ်လုပ်သည်။ Delphi နှင့်လည်း ကောင်းမွန်သည်။ Windows အက်ပ်များကို သိမ်းဆည်းပါ။ Qt5 နှင့် Java အပလီကေးရှင်းအချို့နှင့် အလုပ်လုပ်ပါသည်။ ယေဘုယျအားဖြင့် Inspect.exe သည် element များနှင့် ၎င်းတို့၏ properties များကို မြင်ပါက ဤ backend သည် သင့်လျော်ပါသည်။ အခြေခံအားဖြင့် browser အများစုသည် UI Automation ကိုလည်း ပံ့ပိုးပေးပါသည် (default အားဖြင့် Mozilla ဖြစ်ပြီး Chrome သည် စတင်လိုက်သည်နှင့် command-line switch လိုအပ်သည်)။ --force-renderer-accessibilityInspect.exe ရှိ စာမျက်နှာများရှိ အစိတ်အပိုင်းများကို ကြည့်ရန်)။ ဟုတ်ပါတယ်၊ ဒီနယ်ပယ်မှာ Selenium နဲ့ ပြိုင်ဆိုင်မှုက မဖြစ်နိုင်သလောက်ပါပဲ။ ဘရောက်ဆာနှင့်အလုပ်လုပ်ရန် အခြားနည်းလမ်းတစ်ခုသာဖြစ်သည် (ထုတ်ကုန်ဖြတ်ကျော်မှုအခြေအနေအတွက် အသုံးဝင်နိုင်သည်)။

အလိုအလျောက်စနစ်အတွက် ဝင်ခွင့်အမှတ်များ

အပလီကေးရှင်းကို အကျယ်တဝင့် သုတေသနပြုထားပါတယ်။ အပလီကေးရှင်းအရာဝတ္တုတစ်ခုကိုဖန်တီးပြီး ၎င်းကိုလည်ပတ်ရန် သို့မဟုတ် လုပ်ဆောင်နေပြီးသားတစ်ခုသို့ ပူးတွဲရန် အချိန်ကျရောက်ပြီဖြစ်သည်။ ၎င်းသည် စံအတန်းတစ်ခု၏ မွေးထုတ်ခြင်းမျှသာ မဟုတ်ပါ။ subprocess.Popenဆိုလိုသည်မှာ သင့်လုပ်ဆောင်မှုများအားလုံးကို လုပ်ငန်းစဉ်၏ နယ်နိမိတ်များတွင် ကန့်သတ်ထားသည့် ထည့်သွင်းသည့်အရာဝတ္ထုတစ်ခုဖြစ်သည်။ အပလီကေးရှင်း၏ သာဓကများစွာကို လုပ်ဆောင်နေပါက ၎င်းသည် အလွန်အသုံးဝင်သော်လည်း ကျန်အရာများကို သင်မထိချင်ပါ။

from pywinauto.application import Application
app = Application(backend="uia").start('notepad.exe')

# Опишем окно, которое хотим найти в процессе Notepad.exe
dlg_spec = app.UntitledNotepad
# ждем пока окно реально появится
actionable_dlg = dlg_spec.wait('visible')

အကယ်၍ သင်သည် အပလီကေးရှင်းများစွာကို တစ်ပြိုင်နက် စီမံခန့်ခွဲလိုပါက၊ ဤအတန်းသည် သင့်အား ကူညီပေးပါမည်။ Desktop. ဥပမာအားဖြင့်၊ Win10 ရှိ ဂဏန်းပေါင်းစက်တစ်ခုတွင်၊ လုပ်ငန်းစဉ်အများအပြားတွင် ဒြပ်စင်များ၏ အထက်တန်းအဆင့်ကို ဖြန့်ကြက်ထားသည် (သာမက၊ calc.exe) ဒါကြောင့် အရာဝတ္ထု မရှိဘူး။ Desktop မလုံလောက်။

from subprocess import Popen
from pywinauto import Desktop

Popen('calc.exe', shell=True)
dlg = Desktop(backend="uia").Calculator
dlg.wait('visible')

အမြစ်အရာဝတ္ထု (Application သို့မဟုတ် Desktop) သည် backend ကိုသတ်မှတ်ရန်လိုအပ်သည့်တစ်ခုတည်းသောနေရာဖြစ်သည်။ အခြားအရာအားလုံးသည် “သတ်မှတ်ချက်->ထုပ်ပိုးခြင်း” သဘောတရားတွင် ပွင့်လင်းမြင်သာစွာ ကျရောက်နေပြီး၊ နောက်ပိုင်းတွင် ဆွေးနွေးသွားပါမည်။

Window/Element Specifications

ဤသည်မှာ pywinauto အင်တာဖေ့စ်ကိုတည်ဆောက်ထားသည့် အဓိကသဘောတရားဖြစ်သည်။ ဝင်းဒိုး/ဒြပ်စင်တစ်ခုအား အကြမ်းဖျင်း သို့မဟုတ် ပိုမိုအသေးစိတ်ဖော်ပြနိုင်သော်လည်း ၎င်းသည် မတည်ရှိသေး သို့မဟုတ် ပိတ်ထားပြီးဖြစ်သည်။ Window specification (အရာဝတ္ထု Window Specification) စစ်မှန်သော ဝင်းဒိုး သို့မဟုတ် ဒြပ်စင်ကို ရှာဖွေရမည့် စံနှုန်းများကို သိမ်းဆည်းထားသည်။

အသေးစိတ် ဝင်းဒိုးသတ်မှတ်ချက် ဥပမာ-

>>> dlg_spec = app.window(title='Untitled - Notepad')

>>> dlg_spec
<pywinauto.application.WindowSpecification object at 0x0568B790>

>>> dlg_spec.wrapper_object()
<pywinauto.controls.win32_controls.DialogWrapper object at 0x05639B70>

နည်းလမ်းကို ခေါ်ဆိုခြင်းဖြင့် ဝင်းဒိုးရှာဖွေမှု ကိုယ်တိုင် ဖြစ်ပေါ်သည်။ .wrapper_object(). ၎င်းသည် တကယ့်ပြတင်းပေါက်/ဒြပ်စင် သို့မဟုတ် ပစ်ခြင်းအတွက် အချို့သော “ထုပ်ပိုးခြင်း” ကို ပြန်ပေးသည်။ ElementNotFoundError (တစ်ခါတစ်ရံတွင် ElementAmbiguousErrorဒြပ်စင်များစွာကို တွေ့ရှိပါက၊ ရှာဖွေမှုစံနှုန်းကို ရှင်းလင်းရန် လိုအပ်သည်။ ဤ "wrapper" သည် ဒြပ်စင်တစ်ခုနှင့် လုပ်ဆောင်ချက်အချို့ကို မည်သို့လုပ်ဆောင်ရမည်ကို သိပြီးဖြစ်သည် သို့မဟုတ် ၎င်းမှဒေတာကို လက်ခံရရှိမည်ဖြစ်သည်။

Python သည် ခေါ်ဆိုမှုကို ဖျောက်နိုင်သည်။ .wrapper_object()ထို့ကြောင့် နောက်ဆုံးကုဒ်သည် ပိုတိုလာသည်။ အမှားရှာပြင်ခြင်းအတွက်သာ အသုံးပြုရန် အကြံပြုအပ်ပါသည်။ နောက်လိုင်းနှစ်ကြောင်းက အတူတူပါပဲ-

dlg_spec.wrapper_object().minimize() # debugging
dlg_spec.minimize() # production

ဝင်းဒိုးသတ်မှတ်ချက်အတွက် ရှာဖွေမှုစံနှုန်းများစွာရှိသည်။ ဤသည်မှာ ဥပမာအနည်းငယ်သာဖြစ်သည်။

# могут иметь несколько уровней
app.window(title_re='.* - Notepad$').window(class_name='Edit')

# можно комбинировать критерии (как AND) и не ограничиваться одним процессом приложения
dlg = Desktop(backend="uia").Calculator
dlg.window(auto_id='num8Button', control_type='Button')

ဖြစ်နိုင်ချေရှိသော သတ်မှတ်ချက်များစာရင်းသည် function docs တွင်ရှိသည်။ pywinauto.findwindows.find_elements(…).

attribute နှင့် key ဖြင့်ဝင်ရောက်ခြင်း၏မှော်

Python သည် window specification များကိုဖန်တီးရန်နှင့် object attribute များကို dynamically အသိအမှတ်ပြုရန်လွယ်ကူစေသည်။ __getattribute__) ဟုတ်ပါတယ်၊ တူညီသောကန့်သတ်ချက်များသည် မည်သည့် variable ၏အမည်တွင်မဆို attribute name တွင်ထည့်သွင်းထားပါသည် (နေရာလွတ်များ၊ ကော်မာများ၊ သို့မဟုတ် အခြားအထူးအက္ခရာများထည့်၍မရပါ)။ ကံကောင်းထောက်မစွာ၊ pywinauto သည် typos နှင့် သေးငယ်သောကွဲပြားမှုများကိုခံနိုင်ရည်ရှိသော "အကောင်းဆုံးကိုက်ညီမှု" ရှာဖွေမှုအယ်လဂိုရီသမ်ကိုအသုံးပြုသည်။

app.UntitledNotepad
# то же самое, что
app.window(best_match='UntitledNotepad')

အကယ်၍ သင်သည် ယူနီကုဒ်စာကြောင်းများ (ဥပမာ၊ ရုရှားဘာသာစကားအတွက်)၊ spaces စသည်တို့ကို လိုအပ်နေသေးပါက၊ သင်သည် (ပုံမှန်အဘိဓာန်ကဲ့သို့) သော့ဖြင့် ဝင်ရောက်နိုင်သည်-

app['Untitled - Notepad']
# то же самое, что
app.window(best_match='Untitled - Notepad')

မှော်အမည်များအတွက် စည်းမျဉ်းငါးခု

စံမှော်အမည်များကို မည်သို့ရှာဖွေရမည်နည်း။ မရှာဖွေမီ ဒြပ်စင်သို့ တာဝန်ပေးထားသည့်အရာများ။ အကယ်၍ သင်သည် စံနှုန်းနှင့် လုံလောက်သော တူညီသော အမည်တစ်ခုကို သတ်မှတ်ပါက၊ အစိတ်အပိုင်းကို တွေ့လိမ့်မည်။

  1. ခေါင်းစဉ် (စာသား၊ အမည်အားဖြင့်) app.Properties.OK.click()
  2. စာသားနှင့် ဒြပ်စင်အမျိုးအစားအားဖြင့်- app.Properties.OKButton.click()
  3. အမျိုးအစားနှင့် နံပါတ်အလိုက်- app.Properties.Button3.click() (အမည်များ Button0 и Button1 ပထမဒြပ်နှင့် ချည်နှောင်ထားသည်ကို တွေ့ရသည်၊ Button2 - ဒုတိယ၊ ပြီးမှ အစဉ်လိုက် - ဒါက သမိုင်းမှာ ဖြစ်ပျက်ခဲ့တာပါ)
  4. အငြိမ်စာသား (ဘယ်ဘက် သို့မဟုတ် အပေါ်) နှင့် အမျိုးအစားအားဖြင့်- app.OpenDialog.FileNameEdit.set_text("") (ပြောင်းလဲနေသော စာသားပါသော ဒြပ်စင်များအတွက် အသုံးဝင်သည်)
  5. အမျိုးအစားအလိုက်၊ အတွင်းမှ စာသားဖြင့်- app.Properties.TabControlSharing.select("General")

အများအားဖြင့် စည်းမျဉ်း နှစ်ခု သို့မဟုတ် သုံးခုကို တစ်ချိန်တည်းတွင် ကျင့်သုံးလေ့ရှိပြီး နည်းပါးပါသည်။ ဒြပ်စင်တစ်ခုစီအတွက် မည်သည့်အမည်များရရှိနိုင်သည်ကို စစ်ဆေးရန်၊ သင်နည်းလမ်းကို အသုံးပြုနိုင်သည်။ print_control_identifiers(). ၎င်းသည် ဖန်သားပြင်နှင့် ဖိုင်တစ်ခုသို့ ဒြပ်စင်သစ်တစ်ပင်ကို ပရင့်ထုတ်နိုင်သည်။ ဒြပ်စင်တစ်ခုစီအတွက်၊ ၎င်း၏ စံမှော်အမည်များကို ရိုက်နှိပ်ထားသည်။ ကလေးဒြပ်စင်များ၏ အသေးစိတ်အချက်အလက်များကို ထိုနေရာမှ ကူးယူပြီး ကူးထည့်နိုင်သည်။ ဇာတ်ညွှန်းရှိရလဒ်သည် ဤကဲ့သို့ဖြစ်လိမ့်မည်-

app.Properties.child_window(data-gt-translate-attributes='["title"]' title="Contains:", auto_id="13087", control_type="Edit")

ဒြပ်စင်၏အပင်ကိုယ်တိုင်က များသောအားဖြင့် ကြီးမားသောခြေနင်းအ၀တ်တစ်ခုဖြစ်သည်။

>>> app.Properties.print_control_identifiers()

Control Identifiers:

Dialog - 'Windows NT Properties'    (L688, T518, R1065, B1006)
[u'Windows NT PropertiesDialog', u'Dialog', u'Windows NT Properties']
child_window(data-gt-translate-attributes='["title"]' title="Windows NT Properties", control_type="Window")
   |
   | Image - ''    (L717, T589, R749, B622)
   | [u'', u'0', u'Image1', u'Image0', 'Image', u'1']
   | child_window(auto_id="13057", control_type="Image")
   |
   | Image - ''    (L717, T630, R1035, B632)
   | ['Image2', u'2']
   | child_window(auto_id="13095", control_type="Image")
   |
   | Edit - 'Folder name:'    (L790, T596, R1036, B619)
   | [u'3', 'Edit', u'Edit1', u'Edit0']
   | child_window(data-gt-translate-attributes='["title"]' title="Folder name:", auto_id="13156", control_type="Edit")
   |
   | Static - 'Type:'    (L717, T643, R780, B658)
   | [u'Type:Static', u'Static', u'Static1', u'Static0', u'Type:']
   | child_window(data-gt-translate-attributes='["title"]' title="Type:", auto_id="13080", control_type="Text")
   |
   | Edit - 'Type:'    (L790, T643, R1036, B666)
   | [u'4', 'Edit2', u'Type:Edit']
   | child_window(data-gt-translate-attributes='["title"]' title="Type:", auto_id="13059", control_type="Edit")
   |
   | Static - 'Location:'    (L717, T669, R780, B684)
   | [u'Location:Static', u'Location:', u'Static2']
   | child_window(data-gt-translate-attributes='["title"]' title="Location:", auto_id="13089", control_type="Text")
   |
   | Edit - 'Location:'    (L790, T669, R1036, B692)
   | ['Edit3', u'Location:Edit', u'5']
   | child_window(data-gt-translate-attributes='["title"]' title="Location:", auto_id="13065", control_type="Edit")
   |
   | Static - 'Size:'    (L717, T695, R780, B710)
   | [u'Size:Static', u'Size:', u'Static3']
   | child_window(data-gt-translate-attributes='["title"]' title="Size:", auto_id="13081", control_type="Text")
   |
   | Edit - 'Size:'    (L790, T695, R1036, B718)
   | ['Edit4', u'6', u'Size:Edit']
   | child_window(data-gt-translate-attributes='["title"]' title="Size:", auto_id="13064", control_type="Edit")
   |
   | Static - 'Size on disk:'    (L717, T721, R780, B736)
   | [u'Size on disk:', u'Size on disk:Static', u'Static4']
   | child_window(data-gt-translate-attributes='["title"]' title="Size on disk:", auto_id="13107", control_type="Text")
   |
   | Edit - 'Size on disk:'    (L790, T721, R1036, B744)
   | ['Edit5', u'7', u'Size on disk:Edit']
   | child_window(data-gt-translate-attributes='["title"]' title="Size on disk:", auto_id="13106", control_type="Edit")
   |
   | Static - 'Contains:'    (L717, T747, R780, B762)
   | [u'Contains:1', u'Contains:0', u'Contains:Static', u'Static5', u'Contains:']
   | child_window(data-gt-translate-attributes='["title"]' title="Contains:", auto_id="13088", control_type="Text")
   |
   | Edit - 'Contains:'    (L790, T747, R1036, B770)
   | [u'8', 'Edit6', u'Contains:Edit']
   | child_window(data-gt-translate-attributes='["title"]' title="Contains:", auto_id="13087", control_type="Edit")
   |
   | Image - 'Contains:'    (L717, T773, R1035, B775)
   | [u'Contains:Image', 'Image3', u'Contains:2']
   | child_window(data-gt-translate-attributes='["title"]' title="Contains:", auto_id="13096", control_type="Image")
   |
   | Static - 'Created:'    (L717, T786, R780, B801)
   | [u'Created:', u'Created:Static', u'Static6', u'Created:1', u'Created:0']
   | child_window(data-gt-translate-attributes='["title"]' title="Created:", auto_id="13092", control_type="Text")
   |
   | Edit - 'Created:'    (L790, T786, R1036, B809)
   | [u'Created:Edit', 'Edit7', u'9']
   | child_window(data-gt-translate-attributes='["title"]' title="Created:", auto_id="13072", control_type="Edit")
   |
   | Image - 'Created:'    (L717, T812, R1035, B814)
   | [u'Created:Image', 'Image4', u'Created:2']
   | child_window(data-gt-translate-attributes='["title"]' title="Created:", auto_id="13097", control_type="Image")
   |
   | Static - 'Attributes:'    (L717, T825, R780, B840)
   | [u'Attributes:Static', u'Static7', u'Attributes:']
   | child_window(data-gt-translate-attributes='["title"]' title="Attributes:", auto_id="13091", control_type="Text")
   |
   | CheckBox - 'Read-only (Only applies to files in folder)'    (L790, T825, R1035, B841)
   | [u'CheckBox0', u'CheckBox1', 'CheckBox', u'Read-only (Only applies to files in folder)CheckBox', u'Read-only (Only applies to files in folder)']
   | child_window(data-gt-translate-attributes='["title"]' title="Read-only (Only applies to files in folder)", auto_id="13075", control_type="CheckBox")
   |
   | CheckBox - 'Hidden'    (L790, T848, R865, B864)
   | ['CheckBox2', u'HiddenCheckBox', u'Hidden']
   | child_window(data-gt-translate-attributes='["title"]' title="Hidden", auto_id="13076", control_type="CheckBox")
   |
   | Button - 'Advanced...'    (L930, T845, R1035, B868)
   | [u'Advanced...', u'Advanced...Button', 'Button', u'Button1', u'Button0']
   | child_window(data-gt-translate-attributes='["title"]' title="Advanced...", auto_id="13154", control_type="Button")
   |
   | Button - 'OK'    (L814, T968, R889, B991)
   | ['Button2', u'OK', u'OKButton']
   | child_window(data-gt-translate-attributes='["title"]' title="OK", auto_id="1", control_type="Button")
   |
   | Button - 'Cancel'    (L895, T968, R970, B991)
   | ['Button3', u'CancelButton', u'Cancel']
   | child_window(data-gt-translate-attributes='["title"]' title="Cancel", auto_id="2", control_type="Button")
   |
   | Button - 'Apply'    (L976, T968, R1051, B991)
   | ['Button4', u'ApplyButton', u'Apply']
   | child_window(data-gt-translate-attributes='["title"]' title="Apply", auto_id="12321", control_type="Button")
   |
   | TabControl - ''    (L702, T556, R1051, B962)
   | [u'10', u'TabControlSharing', u'TabControlPrevious Versions', u'TabControlSecurity', u'TabControl', u'TabControlCustomize']
   | child_window(auto_id="12320", control_type="Tab")
   |    |
   |    | TabItem - 'General'    (L704, T558, R753, B576)
   |    | [u'GeneralTabItem', 'TabItem', u'General', u'TabItem0', u'TabItem1']
   |    | child_window(data-gt-translate-attributes='["title"]' title="General", control_type="TabItem")
   |    |
   |    | TabItem - 'Sharing'    (L753, T558, R801, B576)
   |    | [u'Sharing', u'SharingTabItem', 'TabItem2']
   |    | child_window(data-gt-translate-attributes='["title"]' title="Sharing", control_type="TabItem")
   |    |
   |    | TabItem - 'Security'    (L801, T558, R851, B576)
   |    | [u'Security', 'TabItem3', u'SecurityTabItem']
   |    | child_window(data-gt-translate-attributes='["title"]' title="Security", control_type="TabItem")
   |    |
   |    | TabItem - 'Previous Versions'    (L851, T558, R947, B576)
   |    | [u'Previous VersionsTabItem', u'Previous Versions', 'TabItem4']
   |    | child_window(data-gt-translate-attributes='["title"]' title="Previous Versions", control_type="TabItem")
   |    |
   |    | TabItem - 'Customize'    (L947, T558, R1007, B576)
   |    | [u'CustomizeTabItem', 'TabItem5', u'Customize']
   |    | child_window(data-gt-translate-attributes='["title"]' title="Customize", control_type="TabItem")
   |
   | TitleBar - 'None'    (L712, T521, R1057, B549)
   | ['TitleBar', u'11']
   |    |
   |    | Menu - 'System'    (L696, T526, R718, B548)
   |    | [u'System0', u'System', u'System1', u'Menu', u'SystemMenu']
   |    | child_window(data-gt-translate-attributes='["title"]' title="System", auto_id="MenuBar", control_type="MenuBar")
   |    |    |
   |    |    | MenuItem - 'System'    (L696, T526, R718, B548)
   |    |    | [u'System2', u'MenuItem', u'SystemMenuItem']
   |    |    | child_window(data-gt-translate-attributes='["title"]' title="System", control_type="MenuItem")
   |    |
   |    | Button - 'Close'    (L1024, T519, R1058, B549)
   |    | [u'CloseButton', u'Close', 'Button5']
   |    | child_window(data-gt-translate-attributes='["title"]' title="Close", control_type="Button")

အချို့ကိစ္စများတွင်၊ သစ်ပင်တစ်ခုလုံးကို ပုံနှိပ်ခြင်းမှာ နှေးကွေးနိုင်သည် (ဥပမာ၊ iTunes တွင် တက်ဘ်တစ်ခုတွင် ဒြပ်စင်ပေါင်း သုံးထောင်အထိ ရှိသည်)၊ သို့သော် သင်ရွေးချယ်နိုင်သည် depth (အတိမ်အနက်) depth=1 - ဒြပ်သပ်သပ်၊ depth=2 - လက်ငင်းကလေးတွေပဲ ဖြစ်သွားပြီ။ ဖန်တီးရာတွင်လည်း သတ်မှတ်ချက်များ၌ သတ်မှတ်နိုင်သည်။ child_window.

ဥပမာ

ကျွန်ုပ်တို့သည် အဆက်မပြတ် ဖြည့်ဆည်းပေးနေပါသည်။ repository တွင်ဥပမာများစာရင်း. မကြာသေးမီကအရာများထဲတွင် WireShark ကွန်ရက်ခွဲခြမ်းစိတ်ဖြာသူ၏အလိုအလျောက်လုပ်ဆောင်မှုကိုသတိပြုသင့်သည် (၎င်းသည် Qt5 အပလီကေးရှင်းတစ်ခု၏ကောင်းသောဥပမာတစ်ခုဖြစ်သည်၊ ဤတာဝန်ကို GUI မပါဘဲဖြေရှင်းနိုင်သော်လည်း၊ ဖြစ်သောကြောင့်၊ scapy.Sniffer Python အထုပ်မှ scapy) ၎င်း၏ Ribbon toolbar ဖြင့် MS Paint အလိုအလျောက်လုပ်ဆောင်ခြင်း၏ ဥပမာတစ်ခုလည်း ရှိပါသည်။

ကျွန်ုပ်၏ ကျောင်းသားတစ်ဦး ရေးသော နောက်ထပ် ဥပမာကောင်းတစ်ခု။ ဖိုင်တစ်ဖိုင်ကို explorer.exe မှ Google Drive အတွက် Chrome စာမျက်နှာသို့ ဆွဲယူပါ။ (အနည်းငယ်အကြာတွင် main repository သို့ ရွှေ့ပါမည်။)

ထို့အပြင်၊ ကီးဘုတ် (hot keys) နှင့် mouse ဖြစ်ရပ်များကို စာရင်းသွင်းခြင်း၏ ဥပမာတစ်ခု။
hook_and_listen.py.

ကျေးဇူးတင်လွှာ

ပရောဂျက်ကို စဉ်ဆက်မပြတ် ကူညီပံ့ပိုးပေးသူများကို အထူးပင် ကျေးဇူးတင်ရှိပါသည်။ ငါ့အတွက်နဲ့ ချစ်သူများနေ့ ဒါက အမြဲတမ်း ဝါသနာပါ။ UNN မှ ကျွန်ုပ်၏ ကျောင်းသား နှစ်ဦးသည် ဤအကြောင်းအရာနှင့် ပတ်သက်၍ ၎င်းတို့၏ ဘွဲ့ဒီဂရီများကို မကြာသေးမီက ခုခံကာကွယ်ခဲ့သည်။ Александр MS UI Automation အတွက် ပံ့ပိုးကူညီရန် ကြီးမားသော ပံ့ပိုးကူညီမှုတစ်ခုကို ပြုလုပ်ခဲ့ပြီး မကြာသေးမီက စာသားဂုဏ်သတ္တိများကို အခြေခံ၍ "မှတ်တမ်း-ပြန်ဖွင့်ခြင်း" နိယာမကို အခြေခံ၍ အလိုအလျောက်ကုဒ်ထုတ်ပေးခြင်း (၎င်းသည် အရှုပ်ထွေးဆုံးအင်္ဂါရပ်ဖြစ်သည်)၊ ယခုအချိန်အထိ "uia" နောက်ခံအတွက်သာ ဖြစ်သည်။ အိုင်ဗင် backend အသစ်တစ်ခုကို တီထွင်နေပါတယ် Linux AT-SPI (မော်ဂျူးများ) ကို အခြေခံ၍ mouse и keyboard အခြေခံ python-xlib - 0.6.x) ထွက်ရှိပြီးဖြစ်သည်။

ကျွန်ုပ်သည် Python တွင် အလိုအလျောက်စနစ်ဆိုင်ရာ အထူးသင်တန်းကို အချိန်အတော်ကြာ သင်ကြားပေးနေသောကြောင့် အချို့သော မာစတာကျောင်းသားများသည် အိမ်စာလုပ်ကာ အင်္ဂါရပ်ငယ်များ သို့မဟုတ် အလိုအလျောက်စနစ်၏ နမူနာများကို အကောင်အထည်ဖော်ကြသည်။ သုတေသနအဆင့်ရှိ အဓိကအချက်အချို့ကိုလည်း ကျောင်းသားများက တစ်ချိန်က ရှာဖွေတွေ့ရှိခဲ့သည်။ တစ်ခါတစ်ရံတွင် သင်သည် ကုဒ်၏ အရည်အသွေးကို တင်းတင်းကျပ်ကျပ် စောင့်ကြည့်ရန် လိုအပ်သော်လည်း၊ ကုဒ်လွှမ်းခြုံမှု 95% ဝန်းကျင်ရှိသော တည်ငြိမ်သောခွဲခြမ်းစိတ်ဖြာသူများ (QuantifiedCode၊ Codacy နှင့် Landscape) နှင့် cloud ရှိ အလိုအလျောက်စမ်းသပ်မှုများ (AppVeyor ဝန်ဆောင်မှု) သည် ၎င်းအတွက် များစွာအထောက်အကူပြုပါသည်။

သုံးသပ်ချက်များကို ချန်ထားခဲ့ကာ အမှားအယွင်းများကို ဖော်ထုတ်ကာ ဆွဲယူတောင်းဆိုမှုများကို ပေးပို့ကြသူတိုင်းကိုလည်း ကျေးဇူးတင်ပါသည်။

ထပ်လောင်းအရင်းအမြစ်များ

ကျွန်ုပ်တို့သည် မေးခွန်းများကို လိုက်နာသည်။ StackOverflow တွင် tag (မကြာသေးမီကပေါ်လာသည်။ SO ၏ရုရှားဗားရှင်းတွင် tag) နှင့် Toaster တွင် အဓိကစကားလုံးဖြင့်။ ရှိသည် Gitter တွင် ရုရှားဘာသာစကား စကားပြောခန်း.

ကျွန်ုပ်တို့သည် လစဉ် update လုပ်ပါသည်။ GUI စမ်းသပ်ခြင်းအတွက် open-source စာကြည့်တိုက်များ၏ အဆင့်သတ်မှတ်ခြင်း။. GitHub တွင်ကြယ်ပွင့်အရေအတွက်အရ၊ Autohotkey သာလျှင် (သူတို့တွင်အလွန်ကြီးမားသောအသိုင်းအဝိုင်းနှင့်ရှည်လျားသောသမိုင်းကြောင်းရှိသည်) နှင့် PyAutoGUI သည်ပိုမိုမြန်ဆန်လာသည် (၎င်း၏စာရေးဆရာ Al Sweigart ၏စာအုပ်များ၏ရေပန်းစားမှုကြောင့်အဓိကအားဖြင့် - "ငြီးငွေ့စရာများကိုအလိုအလျောက်လုပ်ပါ။ Python” နှင့် အခြား)။

source: www.habr.com

DDoS ကာကွယ်ရေး၊ VPS VDS ဆာဗာများပါသည့် ဆိုက်များအတွက် ယုံကြည်စိတ်ချရသော hosting ကို ဝယ်ယူပါ။ 🔥 DDoS ကာကွယ်မှု၊ VPS VDS ဆာဗာများပါရှိသော ယုံကြည်စိတ်ချရသော ဝဘ်ဆိုက် hosting ကို ဝယ်ယူပါ | ProHoster