通过Bash脚本运行Python脚本出现f-string语法错误求助
PyQt5脚本通过Bash连续运行报错的解决方案
问题描述
我有两个基于PyQt5开发的Python脚本,单独运行时均正常。为实现第一个脚本结束后自动运行第二个脚本,编写了如下Bash脚本:
#!/bin/bash python /FILEPATH/FILE1.py ; python /FILEPATH/FILE2.py
但执行该Bash脚本时,两个脚本均出现错误,错误信息指向第一个脚本第149行、第二个脚本第139行的self.label_2.setText(f'Invalid: {input_str}')语句末尾的单引号。两个脚本仅内部CARD_DICT字典的内容不同,完整代码如下:
import sys import os from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import * from PyQt5.QtGui import QMovie, QPixmap from PyQt5.QtWidgets import * WINDOW_STYLE = ''' background-color:black; color:white; ''' class Ui_Widget(QWidget): # You need to change this CARD_DICT = { # PIN: IMAGE_PATH '1360739516458': 'images/1.png', # Right lung '1360743335192': 'images/2.png', # Left lung apex '1360341692930': 'images/3.png', # Left heart '136073147157207': 'images/4.png', # Spleen '136075353245': 'images/5.png', # Subxiphoid cardiac # '136072179130241': 'images/6.png', # Diaphragm? # '136073133188248': 'images/7.png', # Supra umbilicus # '136035223197177': 'images/8.png', # right lateral # '1360341562547': 'images/9.png', # left lateral # '13607311245156': 'images/10.png', # Sub umbilicus # the following are for testing purposes only '60013620412116': 'images/6.png', # Diaphragm? '13603447120253': 'images/7.png', # Supra umbilicus '1360341002204': 'images/8.png', # right lateral '13607217912415': 'images/9.png', # left lateral '136073209222206': 'images/10.png', # Sub umbilicus } def __init__(self): super(Ui_Widget, self).__init__() self.setWindowTitle('Simulated Ultrasound') # Full screen self.setWindowState(Qt.WindowMaximized) # No close, minimize and miximaze window button self.setWindowFlag(Qt.FramelessWindowHint) self.setAttribute(QtCore.Qt.WA_StyledBackground, True) self.setStyleSheet(WINDOW_STYLE) self.setupUi(self) def setupUi(self, Widget): Widget.setObjectName("Widget") Widget.resize(800, 600) self.verticalLayout_2 = QtWidgets.QVBoxLayout(Widget) self.verticalLayout_2.setObjectName("verticalLayout_2") self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) self.gridLayout.setObjectName("gridLayout") self.label = QtWidgets.QLabel(Widget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) self.label.setSizePolicy(sizePolicy) font = QtGui.QFont() font.setPointSize(50) self.label.setFont(font) self.label.setFrameShape(QtWidgets.QFrame.NoFrame) self.label.setAlignment(QtCore.Qt.AlignCenter) self.label.setObjectName("label") self.gridLayout.addWidget(self.label, 0, 0, 1, 1) self.verticalLayout_2.addLayout(self.gridLayout) self.lineEdit = QtWidgets.QLineEdit(Widget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred ) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth()) self.lineEdit.setSizePolicy(sizePolicy) self.lineEdit.setMinimumSize(QtCore.QSize(780, 0)) self.lineEdit.setAlignment(QtCore.Qt.AlignCenter) self.lineEdit.setObjectName("lineEdit") self.verticalLayout_2.addWidget(self.lineEdit) self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) self.horizontalLayout.setSpacing(10) self.horizontalLayout.setObjectName("horizontalLayout") self.label_2 = QtWidgets.QLabel(Widget) sizePolicy = QtWidgets.QSizePolicy( QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum ) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) self.label_2.setSizePolicy(sizePolicy) self.label_2.setMinimumSize(QtCore.QSize(0, 10)) self.label_2.setObjectName("label_2") self.horizontalLayout.addWidget(self.label_2) spacerItem = QtWidgets.QSpacerItem( 40, 10, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum ) self.horizontalLayout.addItem(spacerItem) self.pushButton = QtWidgets.QPushButton(Widget) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth()) self.pushButton.setSizePolicy(sizePolicy) self.pushButton.setMinimumSize(QtCore.QSize(0, 26)) self.pushButton.setObjectName("pushButton") self.horizontalLayout.addWidget(self.pushButton) self.verticalLayout_2.addLayout(self.horizontalLayout) self.retranslateUi(Widget) QtCore.QMetaObject.connectSlotsByName(Widget) # I think this is the line to change to make it launch another script self.pushButton.pressed.connect(Widget.close) # type: ignore # self.pushButton.pressed.connect(Widget.post_intervention) # type: ignore # Check every time the text line input changed self.lineEdit.textChanged.connect(self.submit_pass) # type: ignore def retranslateUi(self, Widget): _translate = QtCore.QCoreApplication.translate Widget.setWindowTitle(_translate("Widget", "Widget")) self.label.setText(_translate("Widget", "Scan patient to begin")) self.lineEdit.setPlaceholderText(_translate("Widget", "PIN Phrase")) self.label_2.setText(_translate("Widget", "Arthur: PRE-intervention")) self.pushButton.setText(_translate("Widget", "Click here after performing interventions")) def submit_pass_str(self, input_str): """here the application accept user input""" if input_str in self.CARD_DICT: self.display_image(self.CARD_DICT[input_str]) self.label_2.setText('') else: self.label_2.setText(f'Invalid: {input_str}') def display_image(self, path): name, ext = os.path.splitext(path) if ext and ext.lower() == '.gif': movie = QMovie(path) self.label.setMovie(movie) movie.start() else: image = QPixmap(path) self.label.setPixmap(image) self.label.setMinimumSize(1, 1) def submit_pass(self): """Usage example using PIN Phrase input form""" self.submit_pass_str(self.lineEdit.text()) app = QApplication(sys.argv) window = Ui_Widget() window.show() # sys.exit(post_intervention()) sys.exit(app.exec_())
原因分析
- 核心错误是Bash脚本中调用的
python命令默认指向Python 2.x版本,而代码中使用的f-string(f'Invalid: {input_str}')是Python 3.6及以上版本才支持的语法,Python 2.x无法解析该语法,因此报出单引号相关的语法错误。 - 单独运行脚本时,你实际使用的是Python 3环境(比如
python3命令),所以语法没问题;但Bash环境中python命令的默认指向与单独运行时不一致,导致报错。
解决方案
1. 修改Bash脚本,明确指定Python3解释器
将Bash脚本中的python替换为python3(如果系统中Python3的命令是python3),或直接使用Python3的绝对路径:
#!/bin/bash python3 /FILEPATH/FILE1.py python3 /FILEPATH/FILE2.py
注:代码中的分号可省略,换行即可实现脚本顺序执行。
2. 为Python脚本添加Shebang行
在每个Python脚本的最顶部添加以下代码,确保脚本默认使用Python3运行:
#!/usr/bin/env python3
然后给脚本添加可执行权限:
chmod +x /FILEPATH/FILE1.py /FILEPATH/FILE2.py
之后Bash脚本可直接调用脚本文件:
#!/bin/bash /FILEPATH/FILE1.py /FILEPATH/FILE2.py
3. 额外检查:工作目录问题
脚本中图片路径为相对路径(如images/1.png),如果Bash脚本运行时的工作目录不是脚本所在目录,会导致图片加载失败。可在Bash脚本中先切换到脚本目录:
#!/bin/bash cd /FILEPATH/ python3 FILE1.py python3 FILE2.py
内容的提问来源于stack exchange,提问作者user3568395
相关产品推荐
相关产品推荐

