The error AttributeError: ‘PySide6 QtCore Signal’ object has no attribute ‘Connect’ means your signal is being used with the wrong API casing or on the wrong object.
Why AttributeError: ‘PySide6 QtCore Signal’ Object Has No Attribute ‘Connect’ Appears
Qt for Python exposes signals as Python objects that follow PEP-8 style methods. The correct method is connect in lowercase. When code calls .Connect, Python looks for a member with that exact name on the Signal object and fails. The same crash can happen if you call connect on a class attribute instead of an instance, or if your class does not inherit from QObject properly. The runtime is simply telling you that it cannot find the member that you asked for.
Quick check: scan for any .Connect and switch to .connect. Then confirm the signal is accessed through an object instance, not the class itself.
Fix ‘Signal’ Object Has No Attribute ‘connect’ In PySide6 — Causes And Fixes
There are a handful of repeat offenders behind this crash. Use this table to match the symptom to a precise fix without guesswork.
| Cause | What You See | Fix |
|---|---|---|
Using .Connect instead of .connect |
AttributeError on Connect |
Call signal.connect(slot) with lowercase method |
Calling connect on the class, not an instance |
AttributeError on connect or nothing happens |
Instantiate the class and use instance.signal.connect |
Signal declared on a class that does not subclass QObject |
AttributeError on emit or connect |
Subclass QObject and call super().__init__() in __init__ |
| Signal defined as an instance attribute | Signal object not bound correctly | Declare signals as class attributes on the QObject subclass |
| Mismatched signal signature and slot parameters | Type errors when the signal fires | Match the types and count of arguments or use a lambda to adapt |
| Cross-thread signal to a non-Qt object | Slot never runs or crashes under load | Connect to a QObject receiver or post to the main thread |
Correct Signal And Slot Setup In PySide6
The reliable pattern is simple: declare the signal as a class attribute on a class that inherits QObject, create an instance, connect with lowercase connect, then emit with emit.
from PySide6.QtCore import QObject, Signal, Slot
class Worker(QObject):
# class-level declaration
finished = Signal(str)
def __init__(self):
super().__init__()
def run(self):
# do work, then report
self.finished.emit("done")
class View(QObject):
@Slot(str)
def show_status(self, text):
print("status:", text)
worker = Worker()
view = View()
# connect on the INSTANCE, using lowercase connect
worker.finished.connect(view.show_status)
worker.run()
This pattern avoids the crash because the signal lives on a real object, the casing is right, and the class is wired into Qt’s meta-object system via QObject and super().__init__().
Common Mistakes That Trigger The Error
- Using C++ Casing — Writing
.Connector.Emitmirrors C++ habits. In Python, both are lowercase:.connect,.emit. - Connecting On The Class — Calling
MyEmitter.my_signal.connect(...)reaches a descriptor, not a bound signal. Use an instance:my_emitter.my_signal.connect(...). - Skipping QObject Setup — If your emitter does not inherit
QObject, or its constructor does not callsuper().__init__(), the signal will not function. - Defining Signals In __init__ — Signals must be class attributes. If you assign
self.my_signal = Signal()inside__init__, Qt cannot register it. - Wrong Signature — Declaring
Signal(int)but connecting to@Slot(str)causes runtime noise. Keep argument count and types aligned. - Lambda With Missing Args — If the signal emits data but the lambda ignores it incorrectly, you can lose values or break the call. Include placeholders like
lambda value: handler(value). - Thread Jump Without A QObject Target — Emitting from a worker thread into a plain Python function can miss the GUI thread. Point the connection at a
QObjectthat lives in the main thread.
Working Examples You Can Drop In
Lowercase connect And emit
from PySide6.QtCore import QObject, Signal
class Ping(QObject):
pinged = Signal()
def __init__(self):
super().__init__()
def on_ping():
print("ping")
p = Ping()
p.pinged.connect(on_ping)
p.pinged.emit()
Signal With Data And A Typed Slot
from PySide6.QtCore import QObject, Signal, Slot
class Meter(QObject):
reading = Signal(float)
def __init__(self):
super().__init__()
class Display(QObject):
@Slot(float)
def update(self, value: float):
print("reading:", value)
m = Meter()
d = Display()
m.reading.connect(d.update)
m.reading.emit(3.14)
Adapting Arguments With A Lambda
from PySide6.QtCore import QObject, Signal
class Meter(QObject):
reading = Signal(float)
def __init__(self):
super().__init__()
def log(prefix: str, text: str):
print(prefix, text)
meter = Meter()
meter.reading.connect(lambda v: log("value", str(v)))
meter.reading.emit(2.5)
Using Signals Across Threads Safely
Signals are a safe way to move work results from a background thread to the GUI thread. The connection between a worker and a receiver will default to an auto connection. When the objects live on different threads, that behaves as a queued connection, which keeps the GUI responsive.
from PySide6.QtCore import QObject, QThread, Signal, Slot
class Worker(QObject):
done = Signal(str)
def __init__(self):
super().__init__()
def run(self):
# heavy work here
self.done.emit("ok")
class Controller(QObject):
@Slot(str)
def show(self, text):
print("done:", text)
thread = QThread()
worker = Worker()
worker.moveToThread(thread)
ctrl = Controller()
thread.started.connect(worker.run)
worker.done.connect(ctrl.show)
thread.start()
# later, quit cleanly
thread.quit(); thread.wait()
Quick check: keep the worker as a QObject, move it to the thread, connect before starting, and emit results rather than touching widgets from the worker.
Troubleshooting Checklist
- Search And Replace — Replace every
.Connectwith.connectand every.Emitwith.emit. - Verify QObject Lineage — Confirm each emitter inherits
QObjectand callssuper().__init__(). - Inspect Binding — Ensure you call
instance.signal.connect, notClass.signal.connect. - Match Signatures — Align
Signal(...)types with slot parameters or decorate slots with@Slot(...). - Audit Thread Use — For worker threads, emit to a receiver that lives on the main thread.
- Log Connections — Print the receiver function and confirm the slot runs by logging inside it.
Practical Patterns You Can Reuse
These patterns keep code clean and prevent the crash from returning later.
- Emitter Class Per Feature — Group related signals on a small
QObjectclass. Keep names action-based such asdata_readyanderror. - Typed Slots For Clarity — Decorate slots with
@Slot(type)so readers see expectations. It also guards against wrong connections. - Instance-Only Access — Never call
MyClass.signal.connecton the class. Always connect on the object you created. - One Responsibility — Let workers emit plain data and keep UI work inside a receiver that owns widgets on the main thread.
- Tear-Down Paths — When windows close, call
disconnector drop references so queued calls do not land on deleted objects.
Where This Differs From PyQt And C++
PySide6 mirrors Qt but sticks to Python naming. In C++ you call free functions like QObject::connect and emit signals using the language keyword. In PySide6, you call lowercase methods on Python objects: signal.connect and signal.emit. That change in surface area is the reason the uppercase .Connect slips in during porting or while reading C++ posts. Treat the Python API as the source of truth and the error disappears.
Recap: Fixing The Exact Error Fast
To resolve AttributeError: ‘PySide6 QtCore Signal’ object has no attribute ‘Connect’ in a minute, apply this sequence:
- Lowercase The Call — Change
.Connectto.connect. - Use An Instance — Connect on
object.signal, not on the class name. - Subclass QObject — Ensure the emitter inherits
QObjectand callssuper().__init__(). - Keep Signals On The Class — Declare
Signal(...)as a class attribute. - Align Signatures — Match signal arguments with the slot or adapt with a lambda.
Follow that path and the crash vanishes, your connections stay readable, and your slots fire exactly when they should.
