1

I'm having trouble with things breaking based on x86 vs x64 in Python 3 on Windows.

I need to know if my Python program is running:

  • On x64 vs. x86 Hardware
  • On a x64 vs. x86 Operating System
  • In a x64 vs. x86 Process

They are not the same thing (at all!).

AMD64 architecture processors can run either 64 or 32 bit operating systems.

And 64 bit operating systems can run either 64 or 32 bit processes.

I know that:

  • Python's platform.architecture() returns a string - but which of those 3 does it represent? (The documentation doesn't seem to say.)
  • If (sys.maxsize > 2**32) then I'm in a 64 bit process. Fine; but if I'm in 32 bit process how can I tell if I'm on a 64 or 32 bit OS?

To forestall the inevitable "why do you care?" questions, it's because my Python program is automating configuration of Windows - things are in different places on x86 vs x64 Windows, but I don't know in advance if my program will be running on 32 or 64 bit Python.

So I need to figure that out.

martineau
  • 119,623
  • 25
  • 170
  • 301
nerdfever.com
  • 1,652
  • 1
  • 20
  • 41
  • 1
    Things are *not* in different places, or rather, the OS hides the difference. You *shouldn't* be trying to access the `WoW64` or `Program Filex (x86)` folders directly. Application data should't be stored in `Program Files` anyway, that's what `ProgramData` is for. – Panagiotis Kanavos Mar 05 '20 at 17:50
  • So, why do you care? What kind of config automation are you trying to perform and why should the OS bitness matter? There are probably more appropriate ways to do whatever you want, that don't try to bypass the OS – Panagiotis Kanavos Mar 05 '20 at 17:51
  • BTW if you run a 32-bit version of Windows on a x64 processor, you still run on a 32-bit version of Windows. The folders won't change. So the actual processor architecture shouldn't matter. – Panagiotis Kanavos Mar 05 '20 at 17:57
  • Since people are asking - (1) I need to know whether to install x64 or x86 versions of applications (some apps have different install .EXEs based on that), and (2) ONLY if i'm in a 32 bit process on a 64 bit OS, I need to run the 64 bit version of cmd.exe and nbtstat.exe, (3) if on a 32 bit OS I run "SetACL32", but on a 64 bit OS I run "SetACL". Microsoft's attempt to hide the differences works find most of the time - but not for this stuff. (I wish it were otherwise.) – nerdfever.com Mar 05 '20 at 18:02
  • 1) All installers already support packaging multiple targets and deploying the appropriatet one. The `setup.exe` is typically just a bootstrapper that starts the appropriate installer. For 2) there's no separate version that you'd need to call. Unless you *explicitly* try to run the executable using an absolute path. 3) SetACL is a third-party product. You don't need it to set permissions. The built-in command is `cacls` – Panagiotis Kanavos Mar 05 '20 at 18:07
  • Apart from the installer,all the rest is available eg through Powershell. – Panagiotis Kanavos Mar 05 '20 at 18:07
  • @PanagiotisKanavos Alas, the apps are not mine - I don't control the installers. For example, please go talk to the 7Zip people for me and tell them that. Or the Notepad++ people. – nerdfever.com Mar 05 '20 at 18:09
  • They know. They don't provide separate installers because it's impossible, they do so because they want to reduce the download size. The [chocolatey package](https://chocolatey.org/packages/notepadplusplus.install#files) on the other hand installs both. It actually checks the bitness and downloads, installs the correct installer, the way a bootstrapper would – Panagiotis Kanavos Mar 05 '20 at 18:12
  • Keep in mind that Windows *already* has mechanisms for automated management and configuration on thousands of machines in a domain, since 2000. Bank admins for example don't go to each machine to run scripts, they push group policies or Powershell DSC configs to entire business units. If mixed environments were such a problem, they'd be screaming for a decade at least. – Panagiotis Kanavos Mar 05 '20 at 18:20
  • One of the latest configuration mechanisms is PowerShell DSC, which through PowerShell Core, also works on Linux. Check [this blog post](https://octopus.com/blog/getting-started-with-powershell-dsc) for a short description, or this [series of articles](https://www.red-gate.com/simple-talk/sysadmin/powershell/powershell-desired-state-configuration-the-basics/) – Panagiotis Kanavos Mar 05 '20 at 18:22

2 Answers2

1

So your actual question is whether the Windows you're running on is x64? :)

Riffing off this and this, how about

import os
arch = (
    os.environ.get("PROCESSOR_ARCHITEW6432") or 
    os.environ.get("PROCESSOR_ARCHITECTURE")
)
# `arch` should now reliably be `x64` if the system is 64-bit.

AKX
  • 152,115
  • 15
  • 115
  • 172
  • The OP's problem is probably an attempt to write to the WoW64 or `Program Files (x86)` folders directly. Which is a very bad idea, as the OS takes pains to hide the architecture difference. If the Python code runs as 32-bit it will see the Wow64 folders for example – Panagiotis Kanavos Mar 05 '20 at 17:52
  • 1
    Upvoted before testing this thoroughly. It doesn't work. If you run this in a 32 bit process on 64 bit Windows, PROCESSOR_ARCHITEW6432 is 'AMD64' and PROCESSOR_ARCHITECTURE is 'x86'. So this really tests for a 64 bit PROCESS, not the OS. – nerdfever.com Mar 05 '20 at 18:22
  • Yes, but you can't run a x64 process on an x32 OS. – AKX Mar 05 '20 at 18:44
  • 1
    I think @nerdfever.com wants to know if the system *could* run a 64-bit executable, not whether the current Python interpreter is running as a 32 or 64-bit process. e.g. a portable installer might run as 32-bit so it can work and choose what to install even if the system is only 32-bit. Or maybe some other use-case. – Peter Cordes Mar 05 '20 at 19:09
  • @AKX But you can run a 32 bit process in a 64 bit OS. – nerdfever.com Mar 05 '20 at 19:15
  • Yes, you can. In that case, since you'd be running in WoW64, the `PROCESSOR_ARCHITEW6432` would be there, and it'd be `x64`. – AKX Mar 05 '20 at 19:22
0

I believe this will work, but I haven't tested it on a 32-bit version of Windows:

import sys, os
x64_process = (sys.maxsize > 2**32)
x64_os = os.environ.get('ProgramW6432') is not None

And probably my most important use case - restarting explorer.exe after registry changes:

def restartExplorer():
    '''Restart explorer'''
    do(r'taskkill /f /im explorer.exe')
    if x64_os and not x64_process:
        do(os.environ['systemroot']+ r'\sysnative\cmd.exe /c start /B explorer.exe') # because this Python is in a 32 bit process
    else:
        do("start explorer.exe")

I won't give you the implementation of do() because it's pretty obvious. (But will if somebody asks.)

nerdfever.com
  • 1,652
  • 1
  • 20
  • 41