<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      subprocess創(chuàng)建子進(jìn)程,subprocess執(zhí)行py腳本文件,subprocess使用pipenv管理的虛擬環(huán)境執(zhí)行子進(jìn)程

      一、相關(guān)參數(shù)與方法

      》》官方文檔《《

       Popen類:
      subprocess模塊中只定義 了一個(gè)類: Popen。可以使用Popen來創(chuàng)建進(jìn)程,并與進(jìn)程進(jìn)行復(fù)雜的交互。它的構(gòu)造函數(shù)如下: 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) 參數(shù)args可以 是字符串或者序列類型(如:list,元組),用于指定進(jìn)程的可執(zhí)行文件及其參數(shù)。如果是序列類型,第一個(gè)元素通常是可執(zhí)行文件的路 徑。我們也可以顯式的使用executeable參數(shù)來指定可執(zhí)行文件的路徑。在windows操作系統(tǒng)上,Popen通過調(diào)用 CreateProcess()來創(chuàng)建子進(jìn)程,CreateProcess接收一個(gè)字符串參數(shù),如果args是序列類型,系統(tǒng)將會通過 list2cmdline()函數(shù)將序列類型轉(zhuǎn)換為字符串。 參數(shù)bufsize:指定緩沖。我到現(xiàn)在還不清楚這個(gè)參數(shù)的具體含義,望各個(gè)大牛指點(diǎn)。 參數(shù)executable用于指定可執(zhí)行程序。一般情況下我們通過args參數(shù)來設(shè)置所要運(yùn)行的程序。如果將參數(shù)shell設(shè)為 True,executable將指定程序使用的shell。在windows平臺下,默認(rèn)的shell由COMSPEC環(huán)境變量來指定。 參數(shù)stdin, stdout, stderr分別表示程序的標(biāo)準(zhǔn)輸入、輸出、錯(cuò)誤句柄。他們可以是PIPE,文件描述符或文件對象,也可以設(shè)置為None,表示從父進(jìn)程繼承。 參數(shù)preexec_fn只在Unix平臺下有效,用于指定一個(gè)可執(zhí)行對象(callable object),它將在子進(jìn)程運(yùn)行之前被調(diào)用。 參 數(shù)Close_sfs:在windows平臺下,如果close_fds被設(shè)置為True,則新創(chuàng)建的子進(jìn)程將不會繼承父進(jìn)程的輸入、輸出、錯(cuò)誤管 道。我們不能將close_fds設(shè)置為True同時(shí)重定向子進(jìn)程的標(biāo)準(zhǔn)輸入、輸出與錯(cuò)誤(stdin, stdout, stderr)。 如果參數(shù)shell設(shè)為true,程序?qū)⑼ㄟ^shell來執(zhí)行。 參數(shù)cwd用于設(shè)置子進(jìn)程的當(dāng)前目錄。 參數(shù)env是字典類型,用于指定子進(jìn)程的環(huán)境變量。如果env = None,子進(jìn)程的環(huán)境變量將從父進(jìn)程中繼承。 參數(shù)Universal_newlines:不同操作系統(tǒng)下,文本的換行符是不一樣的。如:windows下用'\r\n'表示換,而Linux下用 '\n'。如果將此參數(shù)設(shè)置為True,Python統(tǒng)一把這些換行符當(dāng)作'\n'來處理。 參數(shù)startupinfo與createionflags只在windows下用效,它們將被傳遞給底層的CreateProcess()函數(shù),用 于設(shè)置子進(jìn)程的一些屬性,如:主窗口的外觀,進(jìn)程的優(yōu)先級等等。 subprocess.PIPE 在創(chuàng)建Popen對象時(shí),subprocess.PIPE可以初始化stdin, stdout或stderr參數(shù)。表示與子進(jìn)程通信的標(biāo)準(zhǔn)流。 subprocess.STDOUT 創(chuàng)建Popen對象時(shí),用于初始化stderr參數(shù),表示將錯(cuò)誤通過標(biāo)準(zhǔn)輸出流輸出。 Popen的方法: Popen.poll() 用于檢查子進(jìn)程是否已經(jīng)結(jié)束。None:正在運(yùn)行 0:進(jìn)程正常結(jié)束 1:出現(xiàn)錯(cuò)誤 Popen.wait() 等待子進(jìn)程結(jié)束。設(shè)置并返回returncode屬性。 Popen.communicate(input=None) 與子進(jìn)程進(jìn)行交互。向 stdin發(fā)送數(shù)據(jù),可選參數(shù)input指定發(fā)送到子進(jìn)程的參數(shù)
      或從stdout和stderr中讀取數(shù)據(jù),如使用PIPE時(shí)可以用來讀取數(shù)據(jù),解決子進(jìn)程管道數(shù)據(jù)太多的阻塞:
        stdout,stderr = p.communicate()
      Communicate()返回一個(gè)元組:(stdoutdata, stderrdata)
      注意:如果希望通過進(jìn)程的stdin向其發(fā)送數(shù)據(jù),在創(chuàng)建Popen對象的時(shí)候,參數(shù)stdin必須被設(shè)置為PIPE。
      同樣,如 果希望從stdout和stderr獲取數(shù)據(jù),必須將stdout和stderr設(shè)置為PIPE。 Popen.send_signal(signal) 向子進(jìn)程發(fā)送信號。 Popen.terminate() 停止(stop)子進(jìn)程。在windows平臺下,該方法將調(diào)用Windows API TerminateProcess()來結(jié)束子進(jìn)程。 Popen.kill() 殺死子進(jìn)程。 Popen.stdin 如果在創(chuàng)建Popen對象是,參數(shù)stdin被設(shè)置為PIPE,Popen.stdin將返回一個(gè)文件對象用于策子進(jìn)程發(fā)送指令。否則返回None。 Popen.stdout 如果在創(chuàng)建Popen對象是,參數(shù)stdout被設(shè)置為PIPE,Popen.stdout將返回一個(gè)文件對象用于策子進(jìn)程發(fā)送指令。否則返回 None。 Popen.stderr 如果在創(chuàng)建Popen對象是,參數(shù)stdout被設(shè)置為PIPE,Popen.stdout將返回一個(gè)文件對象用于策子進(jìn)程發(fā)送指令。否則返回 None。 Popen.pid 獲取子進(jìn)程的進(jìn)程ID。 Popen.returncode 獲取進(jìn)程的返回值。如果進(jìn)程還沒有結(jié)束,返回None。

       

      在 Windows 上,args序列被轉(zhuǎn)換為使用以下規(guī)則解析的字符串:

      參數(shù)由空格分隔,空格或制表符。

      被雙引號包圍的字符串被解釋為單個(gè)參數(shù),而不管其中包含的空格。帶引號的字符串可以嵌入到參數(shù)中。

      以反斜杠開頭的雙引號被解釋為文字雙引號。

      反斜杠按字面解釋,除非它們緊跟在雙引號之前。

      如果反斜杠緊跟在雙引號之前,則每一對反斜杠都被解釋為文字反斜杠。如果反斜杠的數(shù)量是奇數(shù),則最后一個(gè)反斜杠會轉(zhuǎn)義下一個(gè)雙引號,如規(guī)則 3 中所述

      二、執(zhí)行py腳本文件  subprocess使用pipenv的虛擬環(huán)境創(chuàng)建子進(jìn)程并向子進(jìn)程傳遞參數(shù)

      創(chuàng)建進(jìn)程的模塊有很多,Python手冊中推薦使用subprocess來替換一些老的模塊和函數(shù),如:os.system、os.spawn*、os.popen*、popen2.*、commands.*

      subprocess.Popen可以使用正式環(huán)境,也可以使用虛擬環(huán)境來創(chuàng)建子進(jìn)程,并且可以向子進(jìn)程傳遞參數(shù)

      1.1 主進(jìn)程文件:

       

      # coding:utf-8
      import subprocess
      import time
      import json
      
      # ++++++++++++++++++++++++++++方式一:正常python環(huán)境下使用++++++++++++++++++++++++++++++++++++++
      # 帶參數(shù)
      # p = subprocess.Popen(['python', './test.py', '參數(shù)1', '參數(shù)2'],stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
      # 不帶參數(shù)
      # p = subprocess.Popen('python ./test.py',stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
      
      
      # ++++++++++++++++++++++++++++++方式二:pipenv管理的的虛擬環(huán)境下運(yùn)行時(shí),就必須要指明pipenv,不指明的話導(dǎo)入虛擬環(huán)境中的模塊就會報(bào)錯(cuò)停止運(yùn)行子進(jìn)程+++++++++++++
      # 不帶參數(shù)
      # p = subprocess.Popen('pipenv run python ./test.py',stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
      # 帶參數(shù) (列表中只能是字符串,其他類型比如字典數(shù)據(jù)需要用json處理成字符串)
      p = subprocess.Popen(['pipenv','run','python','./111.py','參數(shù)1',json.dumps({'1':1,'2':2}),],stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE)
      
      print([x.decode("utf8").strip()  for x in p.stderr.readlines()]) # 打印被執(zhí)行文件的報(bào)錯(cuò)
      
      # 被執(zhí)行文件中所有print打印的內(nèi)容,這個(gè)會等待子進(jìn)程即被執(zhí)行文件執(zhí)行完畢才會輸出
      stdout = p.stdout.readlines()
      result = [x.decode("utf8").strip()  for x in stdout]
      print(result)
      
      # 如果不加p.stdout的輸出的話,主進(jìn)程直接就結(jié)束了,子進(jìn)程自然也不會運(yùn)行,我們可以這樣來測試一下
      # while True:
      #     time.sleep(4)
      #     print('讓子進(jìn)程再運(yùn)行4秒')

       

      1.2 子進(jìn)程test.py文件:

      import '可以放一個(gè)虛擬環(huán)境中安裝的模塊來測試'
      import sys
      print(9999)
      
      if __name__ == "__main__":
          a = sys.argv[1]
          b = sys.argv[2]
          print('argv',sys.argv) # ['./111.py', '參數(shù)1', '參數(shù)2']
          print(b,type(b)) # {"1": 1, "2": 2} <class \'str\'>'
          print(json.loads(b),type(json.loads(b))) # {'1': 1, '2': 2} <class 'dict'>"

      三、subprocess創(chuàng)建子進(jìn)程 執(zhí)行exe可執(zhí)行程序

      # Python手冊中推薦使用subprocess來替換一些老的模塊和函數(shù),如:os.system、os.spawn*、os.popen*、popen2.*、commands.*
      import subprocess
      import psutil
      import time
      def get_pid(pname):
          pid_lis = []
          for proc in psutil.process_iter():
              #print(“pid-%d,name:%s” % (proc.pid,proc.name()))
              if proc.name() == pname:
                  pid_lis.append(proc.pid)
                  # return proc.pid
          return pid_lis
      print(get_pid('WeChat.exe'))
      # subprocess.run(['taskkill', '/f', '/t', '/im', 'WeChat.exe'])
      process = subprocess.Popen('C:\\Program Files (x86)\\Tencent\\WeChat\\WeChat.exe')
      time.sleep(6)
      print(get_pid('WeChat.exe'))
      print('subprocess執(zhí)行命令啟動程序',process.pid)

      四、subprocess.Popen 創(chuàng)建的子進(jìn)程卡死  PIPE管道阻塞問題

      目的:想做一個(gè)雙進(jìn)程,主進(jìn)程持續(xù)運(yùn)行收到服務(wù)端啟動任務(wù),會啟動一個(gè)pipenv管理的自動化腳本main.py的子進(jìn)程,主進(jìn)程受到停止任務(wù),會殺死子進(jìn)程

      嘗試1:使用第一種方式,結(jié)果自動化腳本先運(yùn)行一段時(shí)間,然后假死

      嘗試2:使用第二種方式,主進(jìn)程一直等待子進(jìn)程直到其完畢,那么子進(jìn)程就正常運(yùn)行,但是這顯然不是我的目的,我需要主進(jìn)程子進(jìn)程同時(shí)正常工作

      嘗試3:分析后懷疑是PIPE管道阻塞造成的,就去掉了PIPE,使用默認(rèn)父進(jìn)程的標(biāo)準(zhǔn)輸出,這樣主進(jìn)程和子進(jìn)程就可以都正常工作了

      import subprocess
      import time
      import signal
      def set_signal_handler():
          _flag_quit = True
      
      def main_loop():
          # signal.SIGINT為表示要捕捉的信號,由鍵盤引起的終端(Ctrl c)引起終止程序,第2個(gè)參數(shù)是個(gè)函數(shù)指針,表示捕捉到該信號要執(zhí)行的函數(shù)
          signal.signal(signal.SIGINT, set_signal_handler)
          first_flag = 1
          _flag_quit = False
          wx_pid = None
          popen = None
          while True:
              try:
                  # ctrl+c 結(jié)束程序運(yùn)行,除此之外程序會一直運(yùn)行
                  if _flag_quit:
                      if wx_pid:
                          print('終止子進(jìn)程**************************************', wx_pid)
                          os.system(f"taskkill /t /f /pid {wx_pid}")
                      print('我要停止了')
                      return 'end'
      
                  # 啟動子進(jìn)程
                  if first_flag == 1:
                      first_flag += 1
                      # # 第一種 使用subprocess.PIPE,但是不阻塞:
                      #     # 1.子進(jìn)程會執(zhí)行一段時(shí)間然后就假死了,猜測子進(jìn)程假死原因是subprocess.PIPE中堆積了大量子進(jìn)程的輸出,緩存滿了管道阻塞
                      #     # 2.主進(jìn)程終端命令行不會輸出子進(jìn)程的輸出和日志
                      # popen = subprocess.Popen('pipenv run python ./main.py', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                      #                      stderr=subprocess.PIPE)
       
                      # # 第二種 使用subprocess.PIPE,阻塞:
                      #     # 1.在子進(jìn)程完成前一直等待,子進(jìn)程正常運(yùn)行但是主進(jìn)程會卡在這里什么也不做,直到子進(jìn)程完成
                      #     # 2.主進(jìn)程終端命令行不會輸出子進(jìn)程的輸出和日志,直到子進(jìn)程完成會一股腦輸出到命令行
                      # popen = subprocess.Popen('pipenv run python ./main.py', stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                      #                      stderr=subprocess.PIPE)
                      # print([x.decode("utf8").strip()  for x in p.stderr.readlines()]) # 打印被執(zhí)行文件的報(bào)錯(cuò)
                      # # 被執(zhí)行文件中所有print打印的內(nèi)容,這個(gè)是同步的會阻塞,等待子進(jìn)程即被執(zhí)行文件執(zhí)行完畢才會輸出
                      # stdout = popen.stdout.readlines()
                      # result = [x.decode("utf8").strip()  for x in stdout]
                      # print(stdout,result)
      
                      # 第三種 不使用subprocess.PIPE: 
                          # 1.啟動完子進(jìn)程,主進(jìn)程正常工作,循環(huán)執(zhí)行自己要做的事,子進(jìn)程也會正常執(zhí)行
                          # 沒有使用消息管道PIPE,默認(rèn)繼承父進(jìn)程標(biāo)準(zhǔn)輸出,子進(jìn)程的輸出和日志會和主進(jìn)程的一起顯示在命令行
                      popen = subprocess.Popen('pipenv run python ./main.py')
                      wx_pid = popen.pid
      
                  
                  # 這中間可以做一系列主進(jìn)程要做的動作
                  pass
                  pass
                  pass
                  
      
                  # 有子進(jìn)程的情況下,檢測是否存活
                  if popen:
                      if popen.poll() == 0 or popen.poll() == 1:  # popen.poll(),,None-進(jìn)程未結(jié)束在運(yùn)行、0-進(jìn)程正常結(jié)束、1-錯(cuò)誤
                          # 清空
                          popen = None
      
                  time.sleep(5)
      
              except BaseException as e:
                  print(e)
                  # 停止子進(jìn)程
                  os.system(f"taskkill /t /f /pid {wx_pid}")
                  if popen:
                      wx_pid = None
                      popen = None

       

      五、subprocess.Popen 創(chuàng)建的子進(jìn)程死掉,popen.poll()卻檢測不到的bug

      1.subprocess的bug描述:

      用上面  第四節(jié) 中的代碼創(chuàng)建的子進(jìn)程 wx_pid=popen.pid

      子進(jìn)程中我還開了子線程,然后在主進(jìn)程中用popen.poll()監(jiān)控子進(jìn)程的運(yùn)行狀態(tài)

      有一天子進(jìn)程忽然沒有日志輸出了,我以為是子進(jìn)程和子線程產(chǎn)生了死鎖卡住了

      可是我用進(jìn)程號去系統(tǒng)里面查看,該子進(jìn)程已經(jīng)沒了,但是popen.poll()卻檢測不到,這應(yīng)該是subprocess的一個(gè)bug

      所以不能過分依賴subprocess,應(yīng)該自己檢測子進(jìn)程號的存活狀態(tài)來補(bǔ)充popen.poll()的不足:

      2.python根據(jù)進(jìn)程號檢測進(jìn)程是否存活

      用到 psutil 模塊,需要額外安裝 

      import psutil
      pid = 1136 # int類型
      print(psutil.pid_exists(pid)) # 根據(jù)有無進(jìn)程存在返回 True/False

       

      posted @ 2021-07-02 16:07  www.pu  Views(2220)  Comments(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲综合精品中文字幕| 视频一区视频二区亚洲视频| 欧美亚洲另类制服卡通动漫| 美日韩精品一区二区三区| jk白丝喷浆| 国产精品自拍自在线播放| 舞阳县| 在线精品亚洲区一区二区| 巨爆乳中文字幕爆乳区| 国产一区在线播放av| 久久国产乱子精品免费女| 撕开奶罩揉吮奶头高潮AV| Y111111国产精品久久久| 天堂在线中文| 成人激情视频一区二区三区| 精品国偷自产在线视频99| 免费VA国产高清大片在线| 大乳丰满人妻中文字幕日本| 国产精品偷伦费观看一次 | 米奇影院888奇米色99在线| 国产桃色在线成免费视频| 久久久天堂国产精品女人| 久久国产精品伊人青青草| 国产性色的免费视频网站| 亚洲ΑV久久久噜噜噜噜噜| 成人久久精品国产亚洲av| 国产精品人成视频免费播放| 日韩亚洲精品国产第二页| 伊人久久大香线焦av综合影院| 阿瓦提县| 中文字幕理伦午夜福利片| 伊人欧美在线| 国产精品 视频一区 二区三区| 国产永久免费高清在线观看| 日韩一区二区三区精品区| 超清无码一区二区三区| 激情综合网激情五月伊人| 狠狠做五月深爱婷婷天天综合| 国产国拍亚洲精品永久软件| 波多野结系列18部无码观看AV| 国产成人拍国产亚洲精品|