1

I am trying to split common python code into separate files.

for example I have svr.py with the following code.

import socket

PORT = 6060
SERVER = socket.gethostbyname(socket.gethostname())
ADDRESS = (SERVER, PORT)

__server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
__server.bind(ADDRESS)

def startServer():
   pass

startServer()

so I am thinking of splitting into 2 python files, since the common section (bcode.py) will be use in svr.py and client.py

file: bcode.py has the following code

import socket

PORT = 6060
SERVER = socket.gethostbyname(socket.gethostname())
ADDRESS = (SERVER, PORT)

file: svr.py has the following code

import socket
import bcode

__server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
__server.bind(ADDRESS)

def startServer():
   pass

startServer()

from my understanding when I do import bcode, python interpreter execude bcode.py so it should has constant PORT, SERVER and ADDRESS in memory, but when I run svr.py, I get the following error message:

Traceback (most recent call last):
  File "C:\temp\PythonProject\svr.py", line 9, in <module>
    __server.bind(ADDRESS)
NameError: name 'ADDRESS' is not defined

Process finished with exit code 1

it seems the ADDRESS constant in not available on svr.py even after bcode is imported, and also I need to add import socket on svr.py, I thought since I already import socket in bcode.py and when svr.py import bcode, the import socket is carried into svr.py as well.

I appreciated if you could help me on what is the best way to split common code in Python.

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
user7293420
  • 33
  • 2
  • 7
  • 6
    Ok, you have `import bcode`, but did you mean: `bcode.ADDRESS`? – quamrana Nov 10 '20 at 11:31
  • 5
    Alternatively, `from bcode import ADDRESS` –  Nov 10 '20 at 11:38
  • 1
    .. or even `from bcode import *`. However, I recommend using @quamrana's suggestion: it will always be clear and tidy when your files grow in size. That is, only `import bcode`, and always use the variable by full reference, `__server.bind(bcode.ADDRESS)`. – Wololo Nov 10 '20 at 11:40
  • you have imported bcode and so instead of using `ADDRESS` use `bcode.ADDRESS` – Nalin Angrish Nov 10 '20 at 11:42
  • Does this answer your question? [Visibility of global variables in imported modules](https://stackoverflow.com/questions/15959534/visibility-of-global-variables-in-imported-modules) – SiHa Nov 16 '20 at 08:22

1 Answers1

1

First off, I think it is a very good idea to split your code into modules. It will help you keeping your code clean and tidy!

Then, when you import a module in Python, you decide under what namespace its content is included under. In your example, you've used the standard way of importing, namely import bcode. By this approach, all content of bcode is subject to the bcode namespace and must be referenced as such:

import bcode

print(bcode.ADDRESS)

This is also the approach that I recommend, as it keeps your namespaces clean and tidy when your files grow in number and in terms of code lines. This way, there is never any doubt of which ADDRESS is being used.

However, there are other ways to import modules, e.g. by explicitly importing the variable of choice by from bcode import ADDRESS. But then, imagine doing this,

ADDRESS = "127.0.0.1"

from bcode import ADDRESS

print(ADDRESS) # whatever was in bcode ..

This may be fine for now, but someone else that reads your code may overlook the fact that you rewrote the variable or lose track of which is what and where whatever originally came from.

Yet another approach lets you import all content of a module in under the local namespace by using *. This solution may be acceptable for small scripts, however, you'll probably make it really cumbersome for your future-self (or colleges) as you'll definitely lose control over your names (that is, variables, functions, classes, and so on) in the long run,

ADDRESS = "127.0.0.1"

from bcode import *

print(ADDRESS) # whatever was in bcode ..
print(PORT) # whatever was in bcode ..

I strongly recommend that you stick to the first approach (as you already have), and remember to reference the variables appropriately.

As a final note, you should also be aware of the possibility to rename namespaces/modules. I don't really recommend this either, but it may come in handy for e.g. shortening long modules names. Some heavily used modules from the standard lib have some commonly used abbreviations, e.g. the numpy module, often referenced as just np

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,5,100)
y = x**2
plt.plot(x,y)
Wololo
  • 1,249
  • 1
  • 13
  • 25
  • Hi, Thank you for all the suggestion. I didn't realize that I need to put the name space when referencing the import file, I thought import is similar to include (combine the 2 files into 1 big file hence I just call up the variable name as is). I just try to reference using bcode.ADDRESS and it works. Thank you again. Regards - Haris - – user7293420 Nov 10 '20 at 13:13