1

I'm building a QGIS 3.0 plugin and trying to organise my code into several files. I have three files - a main python script and two other scripts stored in a subfolder. Excerpts provided below:

\myplugin.py:

from .mod import pmp as pmp
from .mod import helpers as h

class MyPlugin:

    def __init__(self, iface):

        self.iface = iface
        [...]
        h.msgInfo(self,"Plugin initialised!")
        pmp.test(self)

\mod\helpers.py:

import qgis.core as qgisCore
from qgis.core import Qgis, QgsApplication, QgsMessageLog
from qgis.gui import QgsMessageBar

def msgInfo(self, message, **kwargs):
    title = kwargs.get('t','')
    dur = kwargs.get('d',10)
    self.iface.messageBar().pushMessage(title, message, level=qgisCore.Qgis.Info, duration=dur)

\mod\pmp.py:

from . import helpers as h

def test(self):
    h.msgInfo(self,"PMP module successfully imported!")

Importing "helpers" is working perfectly for myplugin.py, as the "Plugin initialised!" message is showing as expected. Similarly, importing "pmp" seems to be working for myplugin.py. But when myplugin.py gets to this line:

pmp.test(self)

I get this error:

TypeError: test() takes 0 positional arguments but 1 was given

I've tried "self.pmp.test()" instead, but then of course I get "AttributeError: 'myplugin' object has no attribute 'pmp'".

If I use just "pmp.test()", then pmp.py gives me "NameError: name 'self' is not defined".

  • Why are you trying to pass self around? The self variable is a class idiom and is used by convention inside classes. You only seem to have functions defined and not classes...??? And why are you saving your python files with a .php file extension? – user2856 Jul 13 '18 at 5:03
  • Oops - the .php extensions were typos - they're all .py files. I'll edit the question to fix that. I'm relatively new to python and must admit I don't really understand classes - would that be a better approach here? – Gareth Jones Jul 13 '18 at 5:09
  • P.S. myplugin.py is set up with a class structure (I'll also edit to include that code), as it was generated by a plugin builder plugin, but I haven't done that with the module files. – Gareth Jones Jul 13 '18 at 5:37
2

self is an internal variable that is a reference to the instance of your plugin class.

Don't pass self (itself :) to h.msgInfo, pass the iface object.

\myplugin.py:

from .mod import pmp as pmp
from .mod import helpers as h

class MyPlugin:

    def __init__(self, iface):
        [...]
        h.msgInfo(iface,"Plugin initialised!")
        pmp.test(iface)

        # Or 
        self.iface = iface #if you want to use iface anywhere else inside your MyPlugin class
        [...]
        h.msgInfo(self.iface,"Plugin initialised!")
        pmp.test(self.iface)

\mod\helpers.py:

import qgis.core as qgisCore
from qgis.core import Qgis, QgsApplication, QgsMessageLog
from qgis.gui import QgsMessageBar
[...]
def msgInfo(iface, message, **kwargs):
    title = kwargs.get('t','')
    dur = kwargs.get('d',10)
    iface.messageBar().pushMessage(title, message, level=qgisCore.Qgis.Info, duration=dur)

\mod\pmp.py:

from . import helpers as h

def test(iface):
    h.msgInfo(iface,"PMP module successfully imported!")
  • This doesn't appear to be working. To clarify, the problem is with pmp.py rather than helpers.py - the msgInfo() function in helpers.py was working perfectly, but no longer works if I make the changes you've suggested - I now get "AttributeError: 'QgisInterface' object has no attribute 'iface'." The test() function in pmp.py simply attempts to call the msgInfo() function from helpers.py (which is imported in pmp.py). The code in my original post includes both helpers.py and pmp.py in their entirety. – Gareth Jones Jul 13 '18 at 6:14
  • I've just updated the original post to include the line "self.iface = iface", which was also in the code originally but I had omitted it from my post. – Gareth Jones Jul 13 '18 at 6:19
  • OK, now I feel a little silly. I double-checked and it was definitely just "iface.messageBar()..." rather than "iface.iface.messageBar()..." Interestingly I still got the exact same error if I just used "messageBar()..." without the "iface" at the start... So instead of just reloading the plugin, I shut down QGIS and opened it again, and voila - all works perfectly. Thanks for your help! – Gareth Jones Jul 13 '18 at 6:36
  • Also, I've managed to prevent the error when reloading the plugin inside QGIS by adding "self.iface = None" immediately before "self.iface = iface". – Gareth Jones Jul 13 '18 at 6:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.