最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

pyinstaller打包成無控制臺程序時運行出錯(與popen沖突的解決方法)

 更新時間:2020年04月15日 10:05:44   作者:PurePeace  
這篇文章主要介紹了pyinstaller打包成無控制臺程序時運行出錯(與popen沖突的解決方法),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

有時候我們需要在程序里執(zhí)行一些cmd命令,使用os或者其它模塊中的popen方法去執(zhí)行

這個問題一般是程序內(nèi)有輸入導(dǎo)致的,這個輸入可以是input(),也可以是其它的一些stdin操作(如os.popen實際上會造成輸入請求)

本質(zhì)上就是:使用-w參數(shù)(無控制臺)打包時程序里不要請求輸入

或者,你也可以不用-w參數(shù),手動隱藏控制臺!

有一天,我把使用了os.popen方法的python程序用pyinstaller打包成exe(用了無控制臺打包參數(shù)-w
雙擊運行時程序卻彈框報錯!

我就有點納悶:為什么有控制臺打包出來的exe(不使用-w參數(shù))可以運行,使用-w參數(shù)(無控制臺)打包的卻不能運行呢?

首先,調(diào)用os.popen部分的代碼大概是下面這樣的:

with os.popen('taskkill /f /t /im nginx.exe') as re: # 殺掉nginx
  result = re.read()

執(zhí)行cmd,殺死nginx。

經(jīng)過研究,上結(jié)論:

os.popen 會打開一個管道執(zhí)行命令,而管道是有輸入(stdin)、輸出(stdout) 的!

重點就在輸入(stdin)這里:

當(dāng)我們使用pyinstaller的-w 參數(shù)(或Console=False)打包exe時,python解釋器是不帶控制臺的,

所以它沒有辦法處理輸入(stdin) !
包括使用python的input()函數(shù)也是不行的,都會彈框報錯。

那么怎么辦呢?接著看!

os.popen 實際上是一個簡單的封裝,我們先來看他的原型:subprocess.popen

subprocess.Popen(
	args, 
	bufsize=0, 
	executable=None, 
	stdin=None, 
	stdout=None, 
	stderr=None, 
	preexec_fn=None, 
	close_fds=False, 
	shell=False, 
	cwd=None, 
	env=None, 
	universal_newlines=False, 
	startupinfo=None, 
	creationflags=0
)

簡單的解釋一下(詳細(xì)請看官方文檔):

subprocess官方文檔:https://docs.python.org/2/library/subprocess.html

懶得看解釋可以直接跳過下面這段,直接看解決方法

args 是一個字符串(如cmd命令),或者是包含程序參數(shù)的列表。要執(zhí)行的程序一般就是這個列表的第一項,或者是字符串本身。但是也可以用executable參數(shù)來明確指出。當(dāng)executable參數(shù)不為空時,args里的第一項被認(rèn)為是“命令名”,不同于真正的可執(zhí)行文件的文件名,這個“命令名”是一個用來顯示的名稱,例如執(zhí)行unix/linux下的 ps 命令,顯示出來的就是這個“命令名”。

bufsize 作用就跟python函數(shù)open()buffering參數(shù)一樣:0表示不緩沖,1表示行緩沖,其他正數(shù)表示近似的緩沖區(qū)字節(jié)數(shù),負(fù)數(shù)表示使用系統(tǒng)默認(rèn)值。默認(rèn)是0。

executable 參數(shù)指定要執(zhí)行的程序。它很少會被用到,一般程序可以由args參數(shù)指定。如果shell參數(shù)為True,executable可以用于指定用哪個shell來執(zhí)行(比如bash、csh、zsh等)。windows下,只有當(dāng)你要執(zhí)行的命令是shell內(nèi)建命令(比如dir,copy等) 時,你才需要指定shell=True,而當(dāng)你要執(zhí)行一個基于命令行的批處理腳本(bat啥的)的時候,不需要指定此項。

stdin、stdoutstderr分別表示子程序的標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤。 可選的值有PIPE或者一個有效的文件描述符(其實是個正整數(shù))或者一個文件對象,還有None。如果是PIPE,則表示需要創(chuàng)建一個新的管道,如果是 None,不會做任何重定向工作,子進程的文件描述符會繼承父進程的。另外,stderr的值還可以是STDOUT,表示子進程的標(biāo)準(zhǔn)錯誤也輸出到標(biāo)準(zhǔn)輸出。

如果把preexec_fn設(shè)置為一個可調(diào)用的對象(比如函數(shù)),就會在子進程被執(zhí)行前被調(diào)用。(僅限unix/linux)

如果把close_fds設(shè)置成True,unix/linux下會在開子進程前把除了0、1、2以外的文件描述符都先關(guān)閉。在 Windows下也不會繼承其他文件描述符。

如果把shell設(shè)置成True,指定的命令會在shell里解釋執(zhí)行,這個前面已經(jīng)說得比較詳細(xì)了。

如果cwd(工作目錄)不是None,則會把cwd做為子程序的當(dāng)前目錄。注意,并不會把該目錄做為可執(zhí)行文件的搜索目錄,所以不要把程序文件所在目錄設(shè)置為cwd。

如果env不是None,則子程序的環(huán)境變量由env的值來設(shè)置,而不是默認(rèn)那樣繼承父進程的環(huán)境變量。注意,即使你只在env里定義了某一個環(huán)境變量的值,也會阻止子程序得到其他的父進程的環(huán)境變量(也就是說,如果env里只有1項,那么子進程的環(huán)境變量就 只有1個了)。

如果把universal_newlines設(shè)置成True,則子進程的stdoutstderr被視為文本對象,并且不管是unix/linux的換行符('\n'),還是老mac格式的換行符('\r'),還是windows 格式的換行符('\r\n')都將被視為'\n' 。

如果指定了startupinfocreationflags,它們將會被傳遞給后面的CreateProcess()函數(shù),用于指定子程序的各種其他屬性,比如主窗口樣式或者是子進程的優(yōu)先級等。(僅限Windows)

再解釋一下兩個我們后面要用到的東西:

subprocess.PIPE
一個可以用于Popen的stdin、stdoutstderr參數(shù)的特殊值,它指示應(yīng)打開到標(biāo)準(zhǔn)流的管道。

subprocess.STDOUT
一個可以被用于Popen的stderr參數(shù)的特殊值,表示子程序的標(biāo)準(zhǔn)錯誤與標(biāo)準(zhǔn)輸出匯合到同一句柄。

現(xiàn)在回到我們將要解決的問題

已知:

  • 用pyinstaller的-w參數(shù)打包導(dǎo)致python無法處理輸入值(stdin)
  • os.popen 打開的管道卻需要處理輸入值(stdin)

所以,我們不使用os.popen這個簡單的封裝,改成使用subprocess.popen,接著將subprocess.popen打開管道的輸入值(stdin)重定向,即可解決問題!

請看下列示例:

proc = subprocess.Popen(
  'cmd命令', 
  shell=True, 
  stdout=subprocess.PIPE, 
  stderr=subprocess.STDOUT, 
  stdin=subprocess.PIPE # 重定向輸入值
)
proc.stdin.close() # 既然沒有命令行窗口,那就關(guān)閉輸入
proc.wait()
result = proc.stdout.read() # 讀取cmd執(zhí)行的輸出結(jié)果(是byte類型,需要decode)
proc.stdout.close()

這樣處理后我們用-w參數(shù)打包就不會再報錯了!

也可以將輸出值(stdout)定向到文件輸出,請看:

with open('輸出文件.txt' , 'w+', encoding='utf-8') as out_file:
  proc = subprocess.Popen(
	  'cmd命令', 
	  shell=True, 
	  stdout=out_file, # 注意這里!變成了文件對象!
	  stderr=subprocess.STDOUT, 
	  stdin=subprocess.PIPE
	)
	ret = proc.wait() # 此處其實有返回值
with open('輸出文件.txt', 'r', encoding='utf-8' as read_file:
  output = read_file.read() # 這樣就得到cmd命令的輸出結(jié)果了

稍微封裝一下,就可以直接拿來用了

def execute_cmd(cmd):
	proc = subprocess.Popen(
	  cmd, 
	  shell=True, 
	  stdout=subprocess.PIPE, 
	  stderr=subprocess.STDOUT, 
	  stdin=subprocess.PIPE
	)
	proc.stdin.close()
	proc.wait()
	result = proc.stdout.read().decode('gbk') # 注意你電腦cmd的輸出編碼(中文是gbk)
	proc.stdout.close()
	return result

result = execute_cmd('taskkill /f /t /im nginx.exe')
print(result)

舒服了?。。?!

當(dāng)然,實在要用輸入,又不想要控制臺怎么辦?很簡單,把控制臺隱藏了就行!

下列兩個方法,試試看:

import ctypes
def hideConsole():
  """
  Hides the console window in GUI mode. Necessary for frozen application, because
  this application support both, command line processing AND GUI mode and theirfor
  cannot be run via pythonw.exe.
  """

  whnd = ctypes.windll.kernel32.GetConsoleWindow()
  if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 0)
    # if you wanted to close the handles...
    #ctypes.windll.kernel32.CloseHandle(whnd)

def showConsole():
  """Unhides console window"""
  whnd = ctypes.windll.kernel32.GetConsoleWindow()
  if whnd != 0:
    ctypes.windll.user32.ShowWindow(whnd, 1)

到此這篇關(guān)于pyinstaller打包成無控制臺程序時運行出錯(與popen沖突的解決方法)的文章就介紹到這了,更多相關(guān)pyinstaller打包popen沖突內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于Python參數(shù)解析器argparse的應(yīng)用場景

    關(guān)于Python參數(shù)解析器argparse的應(yīng)用場景

    這篇文章主要介紹了關(guān)于Python參數(shù)解析器argparse的應(yīng)用場景,argparse 模塊使編寫用戶友好的命令行界面變得容易,程序定義了所需的參數(shù),而 argparse 將找出如何從 sys.argv 中解析這些參數(shù),需要的朋友可以參考下
    2023-08-08
  • Python使用random模塊實現(xiàn)擲骰子游戲的示例代碼

    Python使用random模塊實現(xiàn)擲骰子游戲的示例代碼

    這篇文章主要介紹了Python使用random模塊實現(xiàn)擲骰子游戲的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Matlab常用的輸出命令disp與fprintf解讀

    Matlab常用的輸出命令disp與fprintf解讀

    這篇文章主要介紹了Matlab常用的輸出命令disp與fprintf解讀,具有很好的參考價值,希望對大家有所幫助。
    2022-12-12
  • Pandas查詢數(shù)據(jù)df.query的使用

    Pandas查詢數(shù)據(jù)df.query的使用

    本文主要介紹了Pandas查詢數(shù)據(jù)df.query的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Django調(diào)用百度AI接口實現(xiàn)人臉注冊登錄代碼實例

    Django調(diào)用百度AI接口實現(xiàn)人臉注冊登錄代碼實例

    這篇文章主要介紹了Django調(diào)用百度AI接口實現(xiàn)人臉注冊登錄,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Python計算公交發(fā)車時間的完整代碼

    Python計算公交發(fā)車時間的完整代碼

    這篇文章主要介紹了Python計算公交發(fā)車時間的完整代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • Python利用shutil模塊實現(xiàn)文件夾的復(fù)制刪除與裁剪

    Python利用shutil模塊實現(xiàn)文件夾的復(fù)制刪除與裁剪

    shutil模塊是對os模塊的補充,主要針對文件的拷貝、刪除、移動、壓縮和解壓操作。本文將利用shutil模塊實現(xiàn)文件夾的復(fù)制刪除與裁剪,需要的可以參考一下
    2022-05-05
  • Python實現(xiàn)PS圖像調(diào)整黑白效果示例

    Python實現(xiàn)PS圖像調(diào)整黑白效果示例

    這篇文章主要介紹了Python實現(xiàn)PS圖像調(diào)整黑白效果,結(jié)合實例形式分析了Python實現(xiàn)PS圖像的黑白效果原理與相關(guān)操作技巧,需要的朋友可以參考下
    2018-01-01
  • Python中str.join()簡單用法示例

    Python中str.join()簡單用法示例

    這篇文章主要介紹了Python中str.join()簡單用法,結(jié)合實例形式分析了Python中str.join()用于連接生成新字符串的相關(guān)操作技巧,需要的朋友可以參考下
    2018-03-03
  • python根據(jù)給定文件返回文件名和擴展名的方法

    python根據(jù)給定文件返回文件名和擴展名的方法

    這篇文章主要介紹了python根據(jù)給定文件返回文件名和擴展名的方法,實例分析了Python操作文件及字符串的技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03

最新評論

离岛区| 五莲县| 炉霍县| 章丘市| 临漳县| 铁岭县| 庆阳市| 斗六市| 察隅县| 铅山县| 丰宁| 柯坪县| 通州区| 仲巴县| 崇左市| 临夏市| 江城| 英吉沙县| 湖南省| 平利县| 温州市| 巴中市| 南靖县| 阳朔县| 兰考县| 恩平市| 绥芬河市| 潞城市| 淮滨县| 靖远县| 西安市| 鄂托克前旗| 正定县| 平乡县| 普宁市| 鸡泽县| 城固县| 利津县| 广元市| 抚州市| 新乡市|