การส่งผ่านอาร์กิวเมนต์ไปยัง subprocess.call

ฉันเผชิญกับสถานการณ์ที่ไม่พึงประสงค์ด้วยการติดตั้งบางโปรแกรมแบบเงียบ ๆ ฉันไม่แน่ใจว่าพวกเขาใช้แบบแผนใด ๆ สำหรับแฟล็กการติดตั้งที่มีค่า แต่นี่คือสิ่งที่ควรใช้สำหรับการติดตั้ง:

"path with spaces\setup.exe" -uninst -s -f2"path with spaces\uninstall.log"

คุณไม่สามารถใช้ --f2="path with spaces\uninstall.log" หรือ -f2="path with spaces\uninstall.log" หรือ -f2 "path with spaces\uninstall.log"

ดังนั้นถ้าฉันใช้ใน Python ต่อไปนี้:

command = [self.setup_exe, '-uninst', '-s', fr'-f2"{uninstall_log_file}"']

คำสั่งที่กระบวนการย่อยกำลังดำเนินการ (รับจาก subprocess.list2cmdline(command)) คือ:

setup.exe" -uninst -s -f2\"some path\temp build 12\uninstall.log\"

โดยทั่วไปจะมีเครื่องหมายทับปรากฏขึ้นและการติดตั้งล้มเหลว ตามทฤษฎีฉันสามารถสร้างสตริงของตัวเองได้ แต่ผู้ให้บริการรายเดียวกันสำหรับไฟล์ปฏิบัติการอื่นนั้นให้ไวยากรณ์อื่นที่เข้ากันได้กับกระบวนการย่อยมากกว่า ฉันสงสัยว่าเป็นไปได้หรือไม่ที่จะตั้งค่ารายการอาร์กิวเมนต์เพื่อตอบสนองความต้องการของผู้ติดตั้ง?


person Beliaev Maksim    schedule 19.06.2020    source แหล่งที่มา
comment
คุณจะเรียกคำสั่งจริง ๆ ได้อย่างไร? ดูเหมือนว่าคุณอาจใช้ shell=True ในเวลาที่คุณไม่ควรใช้   -  person chepner    schedule 19.06.2020
comment
@chepner คุณพูดถูก ฉันใช้ shell=True เท่าที่ฉันเข้าใจว่าสิ่งนี้จำเป็นในกรณีที่ฉันต้องเรียกใช้คำสั่งในฐานะผู้ใช้ระดับสูง (เช่นกับ PowerShell) หรือมันจะได้ผลทุกกรณี?   -  person Beliaev Maksim    schedule 19.06.2020
comment
ไม่ การใช้ shell=True เพียงสลับจากการรันคำสั่งโดยตรงเป็นการรันเชลล์ด้วยอาร์กิวเมนต์ที่สร้างขึ้น เพื่อให้เชลล์รันคำสั่งแทนคุณ   -  person chepner    schedule 19.06.2020
comment
นี่คือวิธีที่ฉันโทรตอนนี้: subprocess.call(command)   -  person Beliaev Maksim    schedule 19.06.2020
comment
@chepner ตอนนี้กำลังสร้างเครื่องหมายคำพูดอีกชั้น: -f2\some path\uninstall.log\   -  person Beliaev Maksim    schedule 19.06.2020
comment
คุณได้รวมเครื่องหมายคำพูดไว้ในคำจำกัดความของ command: fr'-f2"{uinstall_log_file}"' คุณสามารถละเว้นได้   -  person chepner    schedule 19.06.2020
comment
@chepner น่าเสียดายที่ไม่ใช่ มันกำลังปฏิบัติต่อข้อโต้แย้งทั้งหมดเช่นเดียวกับช่องว่างและทำให้ -f2path..... ใช้งานไม่ได้ :(   -  person Beliaev Maksim    schedule 20.06.2020
comment
ค่าที่แท้จริงของ uninstall_log_file คืออะไร และคำสั่งจริงที่คุณใช้เพื่อรันไฟล์เรียกทำงานคืออะไร   -  person chepner    schedule 20.06.2020
comment
@chepner ดูคำสั่งแรกในคำถาม โดยพื้นฐานแล้วอาจเป็นเส้นทางใดก็ได้ที่มีช่องว่าง มีการร้องขอเส้นทางจากผู้ใช้ ตัวอย่างเช่น C:\Test 1 2 3 4\log.log   -  person Beliaev Maksim    schedule 20.06.2020
comment
นั่นคือวิธีที่คุณอาจเรียกใช้จากบรรทัดคำสั่งของเชลล์ รหัส Python จริงที่คุณใช้รันคำสั่งคืออะไร   -  person chepner    schedule 20.06.2020
comment
ฉันคิดว่าฉันตอบ subprocess.call (คำสั่ง) ฉันลองทั้งแบบเชลล์และไม่ใช่เชลล์   -  person Beliaev Maksim    schedule 22.06.2020
comment
ปัญหาคือคำจำกัดความของคุณของ command ดังที่ฉันอธิบายไว้ก่อนหน้านี้ คุณกำลังเพิ่มเครื่องหมายคำพูดที่มีจุดประสงค์เพื่อป้องกันไม่ให้เชลล์ประมวลผลค่า uninstall_log_file แต่ไม่มี คือ ไม่มีเชลล์ดังกล่าว ลอง command = [..., '-f2', uninstall_log_file]   -  person chepner    schedule 22.06.2020
comment
ฉันพร้อมที่จะยอมแพ้กับไวยากรณ์ที่ใช้สำหรับการเงียบนี้ การสร้างสตริงด้วยตัวเองง่ายกว่า ฉันไม่คิดว่ามันเป็นไปได้ผ่านรายการ   -  person Beliaev Maksim    schedule 22.06.2020
comment
@chepner ไม่ ฉันใช้มันไม่ได้ ไม่สามารถมีช่องว่างระหว่าง -f2 และเส้นทางได้   -  person Beliaev Maksim    schedule 22.06.2020
comment
ตามที่เป็นคำถาม: คุณไม่สามารถใช้ --f2=path กับ spaces\uninstall.log หรือ -f2=path กับ spaces\uninstall.log หรือ -f2 path กับ spaces\uninstall.log   -  person Beliaev Maksim    schedule 22.06.2020


คำตอบ (1)


ถ้าคุณวิ่ง

"path with spaces\setup.exe" -uninst -s -f2"path with spaces\uninstall.log"

จากบรรทัดคำสั่ง การเรียกที่เทียบเท่ากับ subprocess.call คือ

uninstall_log_file = r"path with spaces\uninstall.log"
command = [self.setup_exe, '-uninst', '-s', f'-f2{uninstall_log_file}']
subprocess.call(command)
person chepner    schedule 21.06.2020
comment
น่าเสียดายที่นี่ใช้งานไม่ได้ ฉันลองแล้ว ถ้าฉันใส่เส้นทางโดยไม่มีช่องว่าง มันจะทำงาน ถ้าฉันใส่เส้นทางที่มีช่องว่างแล้วไม่ใช่เพราะอาร์กิวเมนต์จะมีลักษณะเป็น -f2path ที่มีช่องว่าง/log.log ดังนั้นสิ่งนี้จึงไม่ทำงาน - person Beliaev Maksim; 22.06.2020
comment
ฉันลองอันนี้ด้วย: stackoverflow.com/questions/43022687/ แต่ฉันถือว่าผู้ให้บริการแตกต่างกัน เนื่องจากอาร์กิวเมนต์จะมีลักษณะดังนี้ -f2=path มีช่องว่าง ในตัวอย่างของฉันจาก CMD ไม่อนุญาตให้ใช้เครื่องหมายเท่ากับ - person Beliaev Maksim; 22.06.2020
comment
ฉันทำการปรับเปลี่ยนคำตอบเล็กน้อยโดยทำให้ uninstall_log_file เป็นสตริงดิบแทนที่จะเป็น f-string ที่ประมาณค่า ฉันไม่แน่ใจว่าจะสร้างความแตกต่างหรือไม่ - person chepner; 22.06.2020
comment
เพิ่งทำการทดสอบ น่าเสียดายที่ไม่มี ฉันดำเนินการประมวลผลย่อยด้วยรายการ แต่สำหรับการตรวจสอบก็รัน list2cmdline ด้วย กำลังเพิ่มเครื่องหมายคำพูดรอบๆ -f2 -› -f2path การติดตั้งจึงล้มเหลว สิ่งที่ใช้งานได้ แต่แปลกคือ: command = [f'{self.setup_exe}', '-uninst', '-s', fr'-f2{uninstall_log_file}'] command = .join(command) จากนั้นเรียกกระบวนการย่อยด้วย สตริง. คุณคิดว่าเป็นไปได้ไหมที่จะใช้รายการเดียวกัน - person Beliaev Maksim; 23.06.2020